/* * Type definitions for GoJS v3.0.24 * Project: https://gojs.net * Definitions by: Northwoods Software * Definitions: https://github.com/NorthwoodsSoftware/GoJS * Copyright 1998-2025 by Northwoods Software Corporation. * This requires TypeScript v2.8 or later. */ export as namespace go; /** * The ObjectData type is the same as `{ [index: string]: any; }`. * This is to ease writing `someDataObject.anyPropertyName`, * when dealing with arbitrary JavaScript Objects used as model data. * @category Model */ export interface ObjectData { [index: string]: any; } /** * This interface is implemented by the {@link List}, {@link Set}, and {@link Map} * classes; it provides the {@link iterator} read-only property that returns an {@link Iterator}. * * Typical usage is: * ```js * const it = anIterableCollection.iterator; * while (it.next()) { * const item = it.value; * } * ``` * @category Collection */ export interface Iterable { /** * Gets an {@link Iterator} that can iterate over the items in the collection. * * Typical usage is: * ```js * const it = anIterableCollection.iterator; * while (it.next()) { * const item = it.value; * } * ``` */ iterator: Iterator; [Symbol.iterator](): IterableIterator; /** * Returns the first item in the list, or null if there is none. * @returns This returns null if there are no items in the list. */ first(): T | null; /** * This read-only property is the number of elements in the collection. */ readonly count: number; } /** * This interface defines properties and methods for iterating over a collection; * it provides the {@link next} predicate and the {@link value} read-only property. * Some Iterators also provide `key` property values along with each `value`. * * Typical usage is: * ```js * const it = anIterableCollection.iterator; * while (it.next()) { * const item = it.value; * } * ``` * * It is an error if {@link next} is called * after the underlying collection has been modified. * * To avoid confusion when dealing with {@link Iterable}s, * iterators implement the {@link Iterable.iterator} property * by just returning themselves. * @category Collection */ export interface Iterator extends Iterable { /** * Returns itself, which is convenient for code that expects an {@link Iterable} * instead of an {@link Iterator}. */ iterator: Iterator; /** * Call this method to advance the iterator to the next item in the collection. * This should be called before accessing any {@link value}. * @returns whether another item is available; when true the value of {@link value} will be that item. */ next(): boolean; /** * Call this method to advance the iterator to the next item in the collection. * This should be called before accessing any {@link value}. * @returns whether another item is available; when true the value of {@link value} will be that item. */ hasNext(): boolean; /** * Advance if needed to the first item in the collection and return it, or return null if there is none. * * Caution: this returns a *key/value pair*, not a *value*, for {@link Map} iterators. */ first(): T | null; /** * Start this iterator all over again. */ reset(): void; /** * This is true if any invocation of the given predicate on items in the collection is true. * * Call the given predicate on each item in the collection. * As soon as a call returns true, this returns true. * Otherwise this returns false. * For an empty collection this returns false. * * This automatically {@link reset}'s itself when it is called. * @virtual * @param pred - This function must not have any side-effects. * @returns True if any predicate call is true; false otherwise. */ any(pred: (x: T) => boolean): boolean; /** * This is true if all invocations of the given predicate on items in the collection are true. * * Call the given predicate on each item in the collection. * As soon as a call returns false, this returns false. * Otherwise this returns true. * For an empty collection this returns true. * * This automatically {@link reset}'s itself when it is called. * @virtual * @param pred - This function must not have any side-effects. * @returns True if all predicate calls are true; false otherwise. */ all(pred: (x: T) => boolean): boolean; /** * Call the given function on each item in the collection. * * This automatically {@link reset}'s itself when it is called. * @virtual * @param func - This function must not modify the collection. * @returns this iterator itself */ each(func: (x: T) => void): void; /** * Call the given function on each item in the collection and present the results in an iterator. * * This automatically {@link reset}'s itself when it is called. * @virtual * @param func - This function must not modify the collection. * @returns this */ map(func: (x: T) => S): Iterator; /** * Call the given predicate on each item in the collection and for each item that it returns true, present the item in an iterator. * * This automatically {@link reset}'s itself when it is called. * @virtual * @param pred - This function must not have any side-effects. * @returns this */ filter(pred: (x: T) => boolean): Iterator; /** * Gets the current item in the collection, assuming {@link next} has just returned true. */ readonly value: T; /** * Gets the current index to the item in the collection, assuming {@link next} has just returned true. */ readonly key: any; /** * This read-only property is the total number of items in the iterated collection. */ readonly count: number; } /** * This interface defines properties and methods for iterating over a {@link Map}; * it provides the {@link next} predicate and the {@link key} and {@link value} read-only properties. * * Iterating over Maps is very similar to an {@link Iterator}<{@link IKeyValuePair}>, * but not exactly, because the type of the value property is T, not an {@link IKeyValuePair}. * * Typical usage is: * ```js * const it = aMap.iterator; * while (it.next()) { * const key = it.key; * const val = it.value; * } * ``` * @see {@link Iterator} * @category Collection */ export interface IMapIterator { /** {@inheritDoc Iterator.iterator} */ iterator: IMapIterator; /** {@inheritDoc Iterator.next} */ next(): boolean; /** * {@inheritDoc Iterator.hasNext} */ hasNext(): boolean; /** * Advance if needed to the first item in the collection and return it, or return null if there is none. * Returns a *key/value pair*, not a *value*. */ first(): IKeyValuePair | null; /** {@inheritDoc Iterator.reset} */ reset(): void; /** {@inheritDoc Iterator.any} */ any(pred: (x: IKeyValuePair) => boolean): boolean; /** {@inheritDoc Iterator.all} */ all(pred: (x: IKeyValuePair) => boolean): boolean; /** {@inheritDoc Iterator.each} */ each(func: (x: IKeyValuePair) => void): IMapIterator; /** * {@inheritDoc Iterator.map} */ map(func: (x: IKeyValuePair) => S): Iterator; /** * {@inheritDoc Iterator.filter} */ filter(pred: (x: IKeyValuePair) => boolean): Iterator>; /** * Gets the current {@link IKeyValuePair.value|value} in the collection, assuming {@link next} has just returned true. */ readonly value: T; /** * Gets the current {@link IKeyValuePair.key|key} in the collection, assuming {@link next} has just returned true. */ readonly key: K; /** {@inheritDoc Iterator.count} */ readonly count: number; } /** * A (key, value) pair, used in {@link Map}s. * @category Collection */ export interface IKeyValuePair { /** * Gets a key for a value in a {@link Map}. * @returns the key uniquely identifying a {@link value} in a {@link Map}. */ readonly key: K; /** * Gets a value in a {@link Map}. * @returns a value in a {@link Map} corresponding to a {@link key}. */ readonly value: V; } /** * (undocumented) interface used for both the SVGSurface and the CanvasSurface, which are undocumented classes. */ export interface ISurface { width: number; height: number; resize(pixelWidth: number, pixelHeight: number, width: number, height: number): boolean; getBoundingClientRect(): DOMRect; focus(): void; dispose(): void; style: CSSStyleDeclaration; } /** * (undocumented) interface used for both the SVGContext and the CanvasSurfaceContext, which are undocumented classes. */ export interface IContext { fillStyle: string | CanvasGradient | CanvasPattern | SGradient; font: string; globalAlpha: number; lineCap: string; lineDashOffset: number; lineJoin: string; lineWidth: number; miterLimit: number; shadowBlur: number; shadowColor: string; shadowOffsetX: number; shadowOffsetY: number; strokeStyle: string | CanvasGradient | CanvasPattern | SGradient; textAlign: string; imageSmoothingEnabled: boolean; /** Only true if a Spot panel has isClipping element */ clipInsteadOfFill: boolean; filter: string; commitTransform(): void; setImageSmoothingEnabled(smooth: boolean): void; arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, counterclockwise: boolean, lx?: number, ly?: number): void; beginPath(): void; endPath(pathIndex?: number): void; bezierCurveTo(a: number, b: number, c: number, d: number, e: number, f: number): void; clearRect(x: number, y: number, w: number, h: number): void; clip(): void; closePath(): void; createLinearGradient(aX0: number, aY0: number, aX1: number, aY1: number): CanvasGradient | SGradient; createPattern(image: HTMLCanvasElement | HTMLImageElement, repetition: string): CanvasPattern | string; createRadialGradient(aX0: number, aY0: number, aR0: number, aX1: number, aY1: number, aR1: number): CanvasGradient | SGradient; drawImage(src: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement, sx: number, sy: number, sw?: number, sh?: number, dx?: number, dy?: number, dw?: number, dh?: number): void; fill(fillRule: boolean, path: Path2D | null): void; fillRect(x: number, y: number, w: number, h: number): void; fillBackground(x: number, y: number, w: number, h: number): void; fillText(str: string, x: number, y: number): void; getImageData(x: number, y: number, w: number, h: number): ImageData; lineTo(x: number, y: number): void; measureText(text: string): TextMetrics; moveTo(x: number, y: number): void; quadraticCurveTo(a: number, b: number, c: number, d: number): void; rect(x: number, y: number, w: number, h: number): void; restore(): void; rotate(angle: number): void; save(): void; setTransform(a: number, b: number, c: number, d: number, e: number, f: number): void; scale(x: number, y: number): void; stroke(p?: Path2D): void; transform(a: number, b: number, c: number, d: number, e: number, f: number): void; translate(x: number, y: number): void; fillContext(brush: BrushLike, fillRule: boolean, path: Path2D | null): void; strokeContext(): void; shadowsSet(x: number, y: number, blur: number): void; shadowsOff(): void; shadowsOn(): void; enableDash(strokeDashArray: Array, strokeDashOffset: number): void; disableDash(): void; clearContextCache(clearFont: boolean): void; removePartFromView(p: GraphObject): void; createOrUpdateClipGroup(panel: GraphObject, rect: Rect): void; } /** * An ordered iterable collection. * In TypeScript it is a generic class that enforces at compile-time the type of elements that may be added to the List. * * An example usage: * ```js * const list = new go.List(); // or in TypeScript: new go.List(); * list.add(new go.Point(0, 0)); * list.add(new go.Point(20, 10)); * list.add(new go.Point(10, 20)); * // now list.length === 3 * // and list.elt(1) instanceof go.Point * ``` * * You can iterate over the items in a List: * ```js * const it = aList.iterator; * while (it.next()) { * console.log("#" + it.key + " is " + it.value); * } * ``` * Or: * ```js * aList.each(val => { * console.log(val); * }); * ``` * The key will range from zero to {@link count}-1. * * For convenience this **GoJS** List class has synonyms for the following methods and property: * - **get(idx)**: {@link elt} * - **set(idx,val)**: {@link setElt} * - **has(val)**: {@link has} * - **delete(val)**: {@link delete} * - **clear()**: {@link clear} * - **size**: {@link count} * * The constructor now takes an optional Iterable or Array argument that provides the initial elements for the new List. * * Note that GoJS iteration is quite different than ECMAScript iteration, so that functionality has not been made somewhat compatible. * These collection classes were defined in GoJS before the ECMAScript collection classes were proposed. * @category Collection */ export class List implements Iterable { /** * There are two possible constructors: * * `new go.List()`, for JavaScript * * `new go.List()` for TypeScript, to enforce type checking. * * Typical usage would be something like: * ```js * const list = new go.List(); // keep a list of GraphObjects * ``` * @param coll - an optional collection of items to add. */ constructor(coll?: Iterable | Array); /** * This class implements the JavaScript `Symbol.iterator`, * and can be used with spread syntax or `for ... of` statements. */ [Symbol.iterator](): IterableIterator; /** */ toString(): string; /** * Adds a given value to the end of the List. * * Be careful not to call this method while iterating over the collection. * @param val * @returns This modified List. */ add(val: T): this; /** * Adds a given value to the end of the List. * * Be careful not to call this method while iterating over the collection. * @param val */ push(val: T): void; /** * Adds all of the values of a collection to the end of this List. * * Be careful not to call this method while iterating over the collection. * @param coll - the collection of items to add. * @returns This modified List. */ addAll(coll: Iterable | Array): this; /** * Clears the List. * This sets the {@link count} to zero. * * Be careful not to call this method while iterating over the collection. */ clear(): void; /** * Returns whether the given value is in this List. * @param val - The value to check. * @returns Whether or not the value is contained within the List. */ contains(val: T): boolean; /** * Returns whether the given value is in this List. * @param val - The value to check. * @returns Whether or not the value is contained within the List. */ has(val: T): boolean; /** * Returns the index of the given value if it is in this List. * @param val - The value to check. * @returns returns -1 if the value is not in this list. */ indexOf(val: T): number; /** * Returns the element at the given index. * @param i - int The index of the element to return. * @returns the value at the given index. */ elt(i: number): T; /** * Returns the element at the given index. * @param i - int The index of the element to return. * @returns the value at the given index. */ get(i: number): T; /** * Set the element at the given index to a given value. * @param i - int The index of the element to set. * @param val - The value to set at the index. */ setElt(i: number, val: T): void; /** * Set the element at the given index to a given value. * @param i - int The index of the element to set. * @param val - The value to set at the index. */ set(i: number, val: T): void; /** * Returns the first item in the list, or null if there is none. * @returns This returns null if there are no items in the list. */ first(): T | null; /** * Returns the last item in the list, or null if these is none. * @returns This returns null if there are no items in the list. */ last(): T | null; /** * Returns the last item in the list and removes it from the list, or just return null if these is none. * Use {@link add} to push an item onto the end of the list. * Use {@link last} to get the last item without reducing the length of the list. * @returns This returns null if there are no items in the list. */ pop(): T | null; /** * This is true if any invocation of the given predicate on items in the collection is true. * * Call the given predicate on each item in the collection. * As soon as a call returns true, this returns true. * Otherwise this returns false. * For an empty collection this returns false. * @virtual * @param pred - This function must not have any side-effects. * @returns True if any predicate call is true; false otherwise. */ any(pred: ((a: T) => boolean)): boolean; /** * This is true if all invocations of the given predicate on items in the collection are true. * * Call the given predicate on each item in the collection. * As soon as a call returns false, this returns false. * Otherwise this returns true. * For an empty collection this returns true. * @virtual * @param pred - This function must not have any side-effects. * @returns True if all predicate calls are true; false otherwise. */ all(pred: ((a: T) => boolean)): boolean; /** * Call the given function on each item in the collection. * @virtual * @param func - This function must not modify the collection. * @returns This List itself */ each(func: ((a: T) => void)): this; /** * Call the given function on each item in the collection and collect the results in a new List. * * Unlike {@link Iterator.map}, this returns a List, not an Iterator. * @virtual * @param func - This function must not modify the collection. */ map(func: ((a: T) => S)): List; /** * Call the given predicate on each item in the collection and for each item that it returns true, collect the item in a new List. * * Unlike {@link Iterator.filter}, this returns a List, not an Iterator. * @virtual * @param pred - This function must not have any side-effects. */ filter(pred: ((a: T) => boolean)): List; /** * Insert a value before the index i. * * Be careful not to call this method while iterating over the collection. * @param i - int The index to insert before. * @param val - The value to insert. */ insertAt(i: number, val: T): void; /** * Removes a given value (if found) from the List. * * Be careful not to call this method while iterating over the collection. * @param val - The value to remove. * @returns true if the value was found and removed, false otherwise. */ remove(val: T): boolean; /** * Removes a given value (if found) from the List. * * Be careful not to call this method while iterating over the collection. * @param val - The value to remove. * @returns true if the value was found and removed, false otherwise. */ delete(val: T): boolean; /** * Removes a value at a given index from the List. * * Be careful not to call this method while iterating over the collection. * @param i - int The index to remove. */ removeAt(i: number): void; /** * Removes a range of values from the List, given both the starting and the ending zero-based indexes. * For example, * ```js * list.removeRange(2, 4) * ``` * will remove elements 2, 3, and 4 from the list. * If there were two or fewer elements in the list to begin with, the list is unchanged. * If *from* is greater than *to*, the list is unchanged. * If *from* is greater than or equal to the length, the list is unchanged. * If *to* is less than zero, the list is unchanged. * * Be careful not to call this method while iterating over the collection. * @param from - int The starting index of the range to remove, inclusive; negative values are treated as zero * @param to - int The ending index of the range to remove, inclusive; values greater than the length of the list are treated as referring to the last element * @returns This modified List */ removeRange(from: number, to: number): this; /** * Makes a shallow copy of this List. * The values are not copied, * so if they are objects they may continue to be shared with the original List. * @virtual * @returns The new List with the same elements. */ copy(): List; /** * Produces a JavaScript Array from the contents of this List. * @returns A copy of the List in Array form. */ toArray(): Array; /** * Converts the List to a {@link Set | go.Set}. * The count of the resulting Set may be less than the count of this List * if any duplicates were removed. * @returns A copy of the contents of this List, * but with duplicates removed and ordering lost. */ toSet(): Set; /** * Sort the List according to a comparison function. * @param sortfunc - This function is passed two items in the list. * It should return zero if they are equal, * less than zero if the first value should come before the second value, * or greater than zero if the first value should come after the second value. * @returns This modified List. */ sort(sortfunc: ((a: T, b: T) => number)): this; /** * (undocumented) * Sorts a range of consecutive elements in this List based on the given comparison function. * @param sortfunc - This function is passed two elements in the list. * It should return zero if they are equal, * less than zero if the first value should come before the second value, * or greater than zero if the first value should come after the second value. * @param from - int The optional index at which to start the sort, including that element; * default to zero, the first element of the list. * @param to - int The optional index at which to end the sort, excluding that element; * defaults to the end of the list. * @returns This modified List. */ sortRange(sortfunc: ((a: T, b: T) => number), from?: number, to?: number): this; /** * Reverse the order of items in this List. * @returns This modified List. */ reverse(): this; /** * This read-only property is the length of the List. */ get count(): number; /** * This read-only property is the length of the List. */ get size(): number; /** * This read-only property is the length of the List, a synonym for the {@link count} property. */ get length(): number; /** * Gets an object that you can use for iterating over the List. * The key will be an integer from zero to the count-1. * The value will be the item at that index in the list. * Typical usage: * ```js * const it = aList.iterator; * while (it.next()) { * . . . "index: " + it.key + " value: " + it.value . . . * } * ``` */ get iterator(): Iterator; /** * Gets an object that you can use for iterating over the List in backwards order. * The key will be an integer from count-1 to zero. * The value will be the item at that index in the list. * The list is not modified by traversing in reverse order. * Typical usage: * ```js * const it = aList.iteratorBackwards; * while (it.next()) { * . . . 'key: ' + it.key + ' value: ' + it.value . . . * } * ``` */ get iteratorBackwards(): Iterator; } /** * An unordered iterable collection that cannot contain two instances of the same value. * In TypeScript it is a generic class that enforces at compile-time the type of elements that may be added to the Set. * * An example usage: * ```js * const set = new go.Set(); // In TypeScript: new go.Set(); * set.add("orange"); * set.add("apple"); * set.add("orange"); * // now set.size === 2 * // and set.has("orange") === true * // and set.has("banana") === false * ``` * * You can iterate over the items in a Set: * ```js * const it = aSet.iterator; * while (it.next()) { * . . . it.value . . . * } * ``` * Or: * ```js * aSet.each(val => { * . . . val . . . * }); * ``` * * For compatibility with versions of GoJS before version 3.0, the following synonyms are defined: * - **remove(val)**: {@link delete} * - **contains(val)**: {@link has} * - **count**: {@link size} * * The constructor now takes an optional Iterable or Array argument that provides the initial elements for the new Set. * * Note that GoJS iteration is quite different than ECMAScript iteration, so that functionality has not been made somewhat compatible. * These collection classes were defined in GoJS before the ECMAScript collection classes were proposed. * @category Collection */ export class Set implements Iterable { /** * There are two possible constructors: * * `new go.Set()`, for JavaScript * * `new go.Set()` for TypeScript * * In TypeScript, the optional generic argument describes the type of values * that this Set may hold. * * For example, the expression: * ```js * // TypeScript: * new go.Set() * ``` * * Creates a new Set that may only contain {@link Point}s. * * @param coll - an optional collection of items to add. */ constructor(coll?: Iterable | Array); /** * This class implements the JavaScript `Symbol.iterator`, * and can be used with spread syntax or `for ... of` statements. * @since 3.0 */ [Symbol.iterator](): IterableIterator; /** * Return a JavaScript iterator that produces the values in this Set. * This does not produce the old GoJS style {@link Iterator} -- * use the {@link iterator} property if you want that. * @since 3.0 */ values(): IterableIterator; /** */ toString(): string; /** * Adds a given value to the Set, if not already present. * * Be careful not to call this method while iterating over the collection. * @param val - The value to add to the Set; must not be null. * @returns This modified Set. */ add(val: T): this; /** * Adds all of the values of a collection to this Set. * * Be careful not to call this method while iterating over the collection. * @param coll - the collection of items to add. * @returns This modified Set. */ addAll(coll: Iterable | Array): this; /** * Returns whether the given value is in this Set. * @param val - The value to check. * @returns Whether or not the value is contained within the Set. */ has(val: T): boolean; /** * Returns whether the given value is in this Set. * @param val - The value to check. * @returns Whether or not the value is contained within the Set. */ contains(val: T): boolean; /** * Returns true if all of the values of a given collection are in this Set. * @param coll - the collection of items to check for. */ containsAll(coll: Iterable): boolean; /** * Returns true if any of the values of a given collection are in this Set. * @param coll - the collection of items to check for. */ containsAny(coll: Iterable): boolean; /** * Returns the first item in the collection, or null if there is none. * @returns This returns null if there are no items in the collection. */ first(): T | null; /** * This is true if any invocation of the given predicate on items in the collection is true. * * Call the given predicate on each item in the collection. * As soon as a call returns true, this returns true. * Otherwise this returns false. * For an empty collection this returns false. * @virtual * @param pred - This function must not have any side-effects. * @returns True if any predicate call is true; false otherwise. */ any(pred: ((a: T) => boolean)): boolean; /** * This is true if all invocations of the given predicate on items in the collection are true. * * Call the given predicate on each item in the collection. * As soon as a call returns false, this returns false. * Otherwise this returns true. * For an empty collection this returns true. * @virtual * @param pred - This function must not have any side-effects. * @returns True if all predicate calls are true; false otherwise. */ all(pred: ((a: T) => boolean)): boolean; /** * Call the given function on each item in the collection. * @virtual * @param func - This function must not modify the collection. * @returns This Set itself. */ each(func: ((a: T) => void)): this; /** * Call the given function on each item in the collection and collect the results in a new Set. * * Unlike {@link Iterator.map}, this returns a Set, not an Iterator. * @virtual * @param func - This function must not modify the collection. */ map(func: ((a: T) => S)): Set; /** * Call the given predicate on each item in the collection and for each item that it returns true, collect the item in a new Set. * * Unlike {@link Iterator.filter}, this returns a Set, not an Iterator. * @virtual * @param pred - This function must not have any side-effects. */ filter(pred: ((a: T) => boolean)): Set; /** * Removes a value (if found) from the Set. * * Be careful not to call this method while iterating over the collection. * @param val - The value to remove. * @returns true if the value was found and removed, false otherwise. */ delete(val: T): boolean; /** * Removes a value (if found) from the Set. * * Be careful not to call this method while iterating over the collection. * @param val - The value to insert. * @returns true if the value was found and removed, false otherwise. */ remove(val: T): boolean; /** * Removes all of the values of a collection from this Set. * * Be careful not to call this method while iterating over the collection. * @param coll - the collection of items to remove. * @returns This modified Set. */ removeAll(coll: Iterable | Array): this; /** * Removes from this Set all items that are not in the given collection. * * Be careful not to call this method while iterating over the collection. * @param coll - the collection of items that should be kept in this Set. * @returns This modified Set. */ retainAll(coll: Iterable): this; /** * Clears the Set. * This sets the {@link count} to zero. * * Be careful not to call this method while iterating over the collection. */ clear(): void; /** * Makes a shallow copy of this Set. * The values are not copied, * so if they are objects they may continue to be shared with the original Set. * @virtual * @returns The new Set with the same elements. */ copy(): Set; /** * Produces a JavaScript Array from the contents of this Set. * @returns A copy of the Set in Array form. */ toArray(): Array; /** * Converts the Set to a {@link List}. * Because there is no ordering within a Set, * the values in the List may be in any order. * @returns A copy of the contents of this Set in List form. */ toList(): List; /** * This read-only property is the number of elements in the Set. */ get count(): number; /** * This read-only property is the number of elements in the Set. */ get size(): number; /** * Gets an object that you can use for iterating over the Set. * The value will be a member of the Set. * Typical usage: * ```js * const it = aSet.iterator; * while (it.next()) { * . . . " value: " + it.value . . . * } * ``` */ get iterator(): Iterator; /** @hidden */ entries(): IterableIterator<[T, T]>; /** @hidden */ keys(): IterableIterator; /** * Call a provided function once per each key/value pair in this Set. * @param callbackFunc a function to call for each value in the Set * @param thisArg a value to use as this when executing callbackFunc * @since 3.0 */ forEach(callbackFunc: (value1: T, value2: T, map: Set) => void, thisArg: any): void; } /** * An unordered iterable collection of key/value pairs that cannot contain two instances of the same key. * In TypeScript it is a generic class that enforces at compile-time the type of the key and the type of the associated value. * * To create a Map: * ```js * const map = new go.Map(); // In TypeScript: new go.Map(); * map.set("one", 1); * map.set("two", 2); * map.set("three", 3); * // now map.size === 3 * // and map.get("two") === 2 * // and map.has("zero") === false * ``` * * You can iterate over the key/value pairs in a Map: * ```js * const it = aMap.iterator; * while (it.next()) { * console.log(it.key + ": " + it.value); * } * ``` * Or: * ```js * aMap.each(kvp => { * console.log(kvp.key + ": " + kvp.value); * }); * ``` * But note that there is no guaranteed ordering amongst the key/value pairs. * * Call {@link toKeySet} to get a read-only {@link Set | go.Set} that holds all of the keys of a Map. * Iterating over that Set will produce values that are the keys in the Map. * * For compatibility with versions of GoJS before version 3.0, the following synonyms are defined: * - **getValue(key)**: {@link get}, but returns null instead of undefined when key is not present * - **add(key,val)**: {@link set} * - **contains(key)**: {@link has} * - **remove(key)**: {@link delete} * - **count**: {@link size} * * The constructor now takes an optional Iterable or Array argument that provides the initial entries for the new Map. * * Note that GoJS iteration is quite different than ECMAScript iteration, so that functionality has not been made somewhat compatible. * These collection classes were defined in GoJS before the ECMAScript collection classes were proposed. * @category Collection */ export class Map { /** * There are two possible constructors: * * `new go.Map()`, for JavaScript * * `new go.Map()` for TypeScript * * In TypeScript, the two optional generic arguments describe the types of keys * and the types of values that this Map may hold. * * For example, the expression: * ```js * // TypeScript: * new go.Map() * ``` * produces a Map that has keys that must be strings and whose associated values * must be {@link Point}s. * @param coll - an optional collection of {@link IKeyValuePair}s to add, or an Array of {@link IKeyValuePair}s. */ constructor(coll?: Iterable> | Array> | Map); /** * This class implements the JavaScript `Symbol.iterator`, * and can be used with spread syntax or `for ... of` statements. * @since 3.0 */ [Symbol.iterator](): IterableIterator<[K, V]>; /** * Return a JavaScript iterator that produces the entries ([key, value] pairs) of this Map. * This does not produce the old GoJS style {@link Iterator} -- * use the {@link iterator} property if you want that. * @since 3.0 */ entries(): IterableIterator<[K, V]>; /** */ toString(): string; /** * Adds a key-value association to the Map, or replaces the value associated with the key * if the key was already present in the map. * * Be careful not to call this method while iterating over the collection. * @param key - The key or index for storing the value in the Map. * @param val - The value to add to the Map, associated with the key. * @returns This modified Map. */ set(key: K, val: V): this; /** * Adds a key-value association to the Map, or replaces the value associated with the key * if the key was already present in the map. * * Be careful not to call this method while iterating over the collection. * @param key - The key or index for storing the value in the Map. * @param val - The value to add to the Map, associated with the key. * @returns This modified Map. */ add(key: K, val: V): Map; /** * Adds all of the key-value pairs to this Map. * If a key is already present in this Map, * its value is replaced with the corresponding value from the given map. * * Be careful not to call this method while iterating over the collection. * @param coll - the collection of {@link IKeyValuePair}s to add, or an Array of {@link IKeyValuePair}s. * @returns This modified Map. */ addAll(coll: Iterable> | Array> | Map): this; /** * Returns the first {@link IKeyValuePair} in the collection, or null if there is none. * @returns This returns null if there are no items in the collection. */ first(): IKeyValuePair | null; /** * This is true if any invocation of the given predicate on items in the collection is true. * * Call the given predicate on each key/value pair in the collection. * As soon as a call returns true, this returns true. * Otherwise this returns false. * For an empty collection this returns false. * @virtual * @param pred - The argument to the predicate will be an {@link IKeyValuePair}. * This function must not have any side-effects. * @returns True if any predicate call is true; false otherwise. */ any(pred: ((a: IKeyValuePair) => boolean)): boolean; /** * This is true if all invocations of the given predicate on items in the collection are true. * * Call the given predicate on each key/value pair in the collection. * As soon as a call returns false, this returns false. * Otherwise this returns true. * For an empty collection this returns true. * @virtual * @param pred - The argument to the predicate will be an {@link IKeyValuePair}. * This function must not have any side-effects. * @returns True if all predicate calls are true; false otherwise. */ all(pred: ((a: IKeyValuePair) => boolean)): boolean; /** * Call the given function on each key/value pair in the collection. * @virtual * @param func - The argument to the function will be an {@link IKeyValuePair}. * This function must not modify the collection. * @returns This Map itself */ each(func: ((a: IKeyValuePair) => void)): this; /** * Call the given function on each key-value pair in the collection and associate the key with the result of the function in a new Map. * * Unlike {@link Iterator.map}, this returns a Map, not an Iterator. * @virtual * @param func - The argument to the function will be an {@link IKeyValuePair}. * This function must not modify the collection. * @returns a new Map with the same keys but values produced by the function */ map(func: ((a: IKeyValuePair) => S)): Map; /** * Call the given predicate on each key-value pair in the collection and for each pair that it returns true, add the key-value association in a new Map. * * Unlike {@link Iterator.filter}, this returns a Map, not an Iterator. * @virtual * @param pred - This function must not have any side-effects. */ filter(pred: ((a: IKeyValuePair) => boolean)): Map; /** * Returns whether the given key is in this Map. * @param key - The key to look up in the Map. * @returns Whether or not the key is contained within the Map. */ has(key: K): boolean; /** * Returns whether the given key is in this Map. * @param key - The key to look up in the Map. * @returns Whether or not the key is contained within the Map. */ contains(key: K): boolean; /** * Returns the value associated with a key. * @param key - The key to look up in the Map. * @returns The value associated with the given key, or null if not present in the Map. */ get(key: K): V | null; /** * Returns the value associated with a key. * @param key - The key to look up in the Map. * @returns The value associated with the given key, or null if not present in the Map. */ getValue(key: K): V | null; /** * Removes a key (if found) from the Map. * * Be careful not to call this method while iterating over the collection. * @param key - The key to remove. * @returns true if the key was found and removed, false otherwise. */ delete(key: K): boolean; /** * Removes a key (if found) from the Map. * * Be careful not to call this method while iterating over the collection. * @param key - The key to insert. * @returns true if the key was found and removed, false otherwise. */ remove(key: K): boolean; /** * Clears the Map, removing all key-value associations. * This sets the {@link count} to zero. * * Be careful not to call this method while iterating over the collection. */ clear(): void; /** * Makes a shallow copy of this Map. * The keys and their values are not copied, * so if they are objects they may continue to be shared with the original Map. * @virtual * @returns The new Map with copies of the same entries. */ copy(): Map; /** * Produces a JavaScript Array of key/value pair objects from the contents of this Map. * @returns A copy of the Map in Array form, each element being an {@link IKeyValuePair} */ toArray(): Array>; /** * Produces a {@link Set | go.Set} that provides a read-only view onto the keys of this Map. * The collection of keys is not copied. */ toKeySet(): Set; /** * This read-only property is the number of associations in the Map. */ get count(): number; /** * This read-only property is the number of associations in the Map. */ get size(): number; /** * Gets an object that you can use for iterating over the key-value pairs of a Map. * Typical usage: * ```js * const it = aMap.iterator; * while (it.next()) { * console.log("the key: " + it.key + " has value: " + it.value); * } * ``` */ get iterator(): IMapIterator; /** * Gets an object that you can use for iterating over the keys of a Map. * Typical usage: * ```js * const it = aMap.iteratorKeys; * while (it.next()) { * console.log("key: " + it.value); * } * ``` */ get iteratorKeys(): Iterator; /** * Return a JavaScript iterator that produces the keys of this Map. * This does not produce the old GoJS style {@link Iterator} -- * use the {@link iteratorKeys} property if you want that. * @since 3.0 */ keys(): IterableIterator; /** * Gets an object that you can use for iterating over the values of a Map. * Typical usage: * ```js * const it = aMap.iteratorValues; * while (it.next()) { * console.log("value: " + it.value); * } * ``` */ get iteratorValues(): Iterator; /** * Return a JavaScript iterator that produces the values of this Map. * This does not produce the old GoJS style {@link Iterator} -- * use the {@link iteratorValues} property if you want that. * @since 3.0 */ values(): IterableIterator; /** * Call a provided function once per each key/value pair in this Map. * @param callbackFunc a function to call for each entry of the Map * @param thisArg a value to use as this when executing callbackFunc * @since 3.0 */ forEach(callbackFunc: (value: V, key: K, map: Map) => void, thisArg: any): void; } /** * A Point represents an x- and y-coordinate pair in two-dimensional space. * * Use the static functions {@link Point.parse} and {@link Point.stringify} to convert to and from * a standard string representation that is independent of the current locale. * * When an instance of this class is the value of a property of a {@link GraphObject} class or {@link Diagram} * or {@link CommandHandler} or a {@link Tool} class, you should treat the object * as if it were frozen or read-only -- you cannot modify its properties. * This allows the property to return a value without allocating a new instance. * If you need to do your own calculations with the value, call {@link copy} to make * a new instance with the same values that you can modify. * * Many methods modify the object's properties and then return a reference to "this" object. * The only instance method to allocate a new object is the {@link copy} method. * The static {@link Point.parse} method also allocates a new object. * * The "Debug" implementation of this class is significantly slower than the "Release" implementation, * mostly due to additional error checking. * * You cannot inherit from this class. * @category Geometry */ export class Point { /** * The default constructor produces the Point(0,0). * This constructor may take either zero arguments or two arguments. * @param x - The x value. * @param y - The y value. */ constructor(x?: number, y?: number); /** * Modify this Point with new X and Y values. * @param x * @param y * @returns this. */ setTo(x: number, y: number): this; /** * Modify this Point so that its X and Y values are the same as the given Point. * @param p - the given Point. * @returns this. */ set(p: Point): this; /** * Create a copy of this Point, with the same values. * @virtual */ copy(): Point; /** * This static function can be used to read in a {@link Point} from a string that was produced by {@link Point.stringify}. * * `go.Point.parse("1 2")` produces the Point `new go.Point(1, 2)`. * @param str */ static parse(str: string): Point; /** * This static function can be used to write out a {@link Point} as a string that can be read by {@link Point.parse}. * * `go.Point.stringify(new go.Point(1, 2))` produces the string "1 2". * @param val */ static stringify(val: Point): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Point's values as numbers with a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * * Example: * ```js * new go.Binding("location", "loc", go.Point.parse, go.Point.stringifyFixed(2)) * ``` * @param digits must be a non-negative integer * @returns a function that converts a Point to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Point) => string; /** * Indicates whether the given Point is equal to this Point. * @param p - The Point to compare to the current Point. * @returns True if the two Points have identical X and Y values, * false otherwise. * @see {@link equalTo} */ equals(p: Point): boolean; /** * Indicates whether the given point (x, y) is equal to this Point. * @param x * @param y * @returns True if the two Points have identical X and Y values, * false otherwise. * @see {@link equals} */ equalTo(x: number, y: number): boolean; /** * (undocumented) * True when the given Point is nearly equal to this Point. * @param p - The Point to compare to the current Point. * @returns True if the two Points have X and Y values that * are equal with a tolerance of 0.5, false otherwise. */ equalsApprox(p: Point): boolean; /** * Modify this point so that is the sum of the current Point and the * x and y co-ordinates of the given Point. * @param p - The Point to add to this Point. * @returns this. * @see {@link offset} * @see {@link subtract} */ add(p: Point): this; /** * Modify this point so that is the difference of this Point and the * x and y co-ordinates of the given Point. * @param p - The Point to subtract from the current Point. * @returns this. * @see {@link offset} * @see {@link add} */ subtract(p: Point): this; /** * Modify this point by shifting its values with the given DX and DY offsets. * @param dx * @param dy * @returns this. * @see {@link add} * @see {@link subtract} */ offset(dx: number, dy: number): this; /** * Modify this Point so that has been rotated about the origin by the given angle. * @param angle - an angle in degrees. * @returns this. */ rotate(angle: number): this; /** * Modify this Point so that its X and Y values have been scaled by given factors along the X and Y axes. * @param sx * @param sy * @returns this. */ scale(sx: number, sy: number): this; /** * Returns the square of the distance from this Point to a given Point. * @param p - the other Point to measure to. * @returns the square of the euclidean distance. * @see {@link distanceSquared} */ distanceSquaredPoint(p: Point): number; /** * Returns the square of the distance from this point to a given point (px, py). * @param px * @param py * @returns the square of the euclidean distance. * @see {@link distanceSquaredPoint} */ distanceSquared(px: number, py: number): number; /** * Modify this Point so that its X and Y values have been normalized to a unit length. * However, if this Point is the origin (zero, zero), its length remains zero. * @returns this. */ normalize(): this; /** * Compute the angle from this Point to a given Point. * However, if the given Point is the same as this Point, the direction is zero. * @param p - the other Point to which to measure the relative angle. * @returns the angle, in degrees, of the line from this Point to the given point. * @see {@link direction} */ directionPoint(p: Point): number; /** * Compute the angle from this Point to a given (px,py) point. * However, if the point is the same as this Point, the direction is zero. * @param px * @param py * @returns the angle, in degrees, of the line from this Point to the given point. * @see {@link directionPoint} */ direction(px: number, py: number): number; /** * This static function compares a point with a finite line segment. * * If the point is on the finite line segment, this returns zero. * If the point is on the left side of the segment, this returns a positive number. * If the point is on the right side of the segment, this returns a negative number. * If the point is on the infinitely extended line but not within the segment, * then this returns a positive number if the point is beyond the end of the segment when going from A1 to A2, * or this returns a negative number if the point comes before the segment's start at A1. * @param a1x * @param a1y * @param a2x * @param a2y * @param px * @param py * @returns <0 if on the right side, or >0 if on the left side, or zero if exactly on the finite line segment * @since 2.2 */ static compareWithLineSegment(a1x: number, a1y: number, a2x: number, a2y: number, px: number, py: number): number; /** * Compare this point with a finite line segment given by two Points. * * This method compares this point with a finite line segment determined by the given two Points. * If the point is on the finite line segment, this returns zero. * If the point is on the left side of the segment, this returns a positive number. * If the point is on the right side of the segment, this returns a negative number. * If the point is on the infinitely extended line but not within the segment, * then this returns a positive number if the point is beyond the end of the segment when going from A1 to A2, * or this returns a negative number if the point comes before the segment's start at A1. * @param p - the start of the finite line segment * @param q - the end of the finite line segment * @returns <0 if this Point is on the right side of the line segment, or >0 if this Point is on the left side, or zero if exactly on the finite line segment * @since 2.2 */ compareWithLineSegmentPoint(p: Point, q: Point): number; /** * This static function is true if two finite straight line segments intersect each other. * @param a1x * @param a1y * @param a2x * @param a2y * @param b1x * @param b1y * @param b2x * @param b2y * @returns True if the two given finite line segments intersect with each other, false otherwise. * @since 2.2 */ static intersectingLineSegments(a1x: number, a1y: number, a2x: number, a2y: number, b1x: number, b1y: number, b2x: number, b2y: number): boolean; /** * Modify this point to be the closest point to this point that is on a finite line segment. * @param px - one end of the finite line segment * @param py - one end of the finite line segment * @param qx - the other end of the finite line segment * @param qy - the other end of the finite line segment * @returns this modified Point */ projectOntoLineSegment(px: number, py: number, qx: number, qy: number): this; /** * Modify this point to be the closest point to this point that is on a finite line segment. * @param p - one end of the finite line segment * @param q - the other end of the finite line segment * @returns this modified Point */ projectOntoLineSegmentPoint(p: Point, q: Point): this; /** * Modify this point to be at the nearest point on an infinite grid, * given the grid's origin and size of each grid cell. * @param originx - the top-left point of one of the grid cells * @param originy - the top-left point of one of the grid cells * @param cellwidth - the size of each grid cell -- must be a real number larger than zero * @param cellheight - the size of each grid cell -- must be a real number larger than zero * @returns this modified Point */ snapToGrid(originx: number, originy: number, cellwidth: number, cellheight: number): this; /** * Modify this point to be at the nearest point on an infinite grid, * given the grid's origin and size of each grid cell. * @param origin - the top-left point of one of the grid cells * @param cellsize - the size of each grid cell * @returns this modified Point */ snapToGridPoint(origin: Point, cellsize: Size): this; /** * Modify this Point so that its X and Y values correspond to a particular {@link Spot} * in a given Rect. * * The result is meaningless if {@link Spot.isNoSpot} is true for the given Spot. * @param r - the Rect for which we are finding the point. * @param spot - the Spot; {@link Spot.isSpot} must be true for this Spot. * @returns this. * @see {@link setSpot} */ setRectSpot(r: Rect, spot: Spot): this; /** * Modify this Point so that its X and Y values correspond to a particular {@link Spot} * in a given rectangle. * * The result is meaningless if {@link Spot.isNoSpot} is true for the given Spot. * @param x - The X coordinate of the Rect for which we are finding the point. * @param y - The Y coordinate of the Rect for which we are finding the point. * @param w - The Width of the Rect for which we are finding the point. * @param h - The Height of the Rect for which we are finding the point. * @param spot - the Spot; {@link Spot.isSpot} must be true for this Spot. * @returns this the point of the spot in the rectangle. * @see {@link setRectSpot} */ setSpot(x: number, y: number, w: number, h: number, spot: Spot): this; /** * This static function returns the square of the distance from the point P * to the finite line segment from point A to point B. * @param px * @param py * @param ax * @param ay * @param bx * @param by * @returns the euclidean distance. */ static distanceLineSegmentSquared(px: number, py: number, ax: number, ay: number, bx: number, by: number): number; /** * This static function returns the square of the distance from the point P to the point Q. * @param px * @param py * @param qx * @param qy */ static distanceSquared(px: number, py: number, qx: number, qy: number): number; /** * This static function returns the angle in degrees of the line from point P to point Q. * @param px * @param py * @param qx * @param qy */ static direction(px: number, py: number, qx: number, qy: number): number; /** * Gets or sets the x value of the Point. */ get x(): number; set x(value: number); /** * Gets or sets the y value of the Point. */ get y(): number; set y(value: number); /** * True if this Point has X and Y values that are real numbers and not infinity. */ isReal(): boolean; } /** * A Size describes a width and a height in two-dimensional coordinates. * The width and height must both be non-negative. * * Use the static functions {@link Size.parse} and {@link Size.stringify} to convert to and from * a standard string representation that is independent of the current locale. * * When an instance of this class is the value of a property of a {@link GraphObject} class or {@link Diagram} * or {@link CommandHandler} or a {@link Tool} class, you should treat the object * as if it were frozen or read-only -- you cannot modify its properties. * This allows the property to return a value without allocating a new instance. * If you need to do your own calculations with the value, call {@link copy} to make * a new instance with the same values that you can modify. * * Many methods modify the object's properties and then return a reference to "this" object. * The only instance method to allocate a new object is the {@link copy} method. * The static {@link Size.parse} method also allocates a new object. * * The "Debug" implementation of this class is significantly slower than the "Release" implementation, * mostly due to additional error checking. * * You cannot inherit from this class. * @category Geometry */ export class Size { /** * The default constructor produces the Size(0,0). * This constructor may take either zero arguments or two arguments. * @param w - The initial width (must be non-negative). * @param h - The initial height (must be non-negative). */ constructor(w?: number, h?: number); /** * Modify this Size with new Width and Height values. * @param w - the width. * @param h - the height. * @returns this. */ setTo(w: number, h: number): this; /** * Modify this Size so that its Width and Height values are the same as the given Size. * @param s - the given Size. * @returns this. */ set(s: Size): this; /** * Create a copy of this Size, with the same values. * @virtual */ copy(): Size; /** * This static function can be used to read in a {@link Size} from a string that was produced by {@link Size.stringify}. * * `go.Size.parse("1 2")` produces the Size `new go.Size(1, 2)`. * @param str */ static parse(str: string): Size; /** * This static function can be used to write out a {@link Size} as a string that can be read by {@link Size.parse}. * * `go.Size.stringify(new go.Size(1, 2))` produces the string "1 2". * @param val */ static stringify(val: Size): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Size's values as numbers with a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * * Example: * ```js * new go.Binding("desiredSize", "size", go.Size.parse, go.Size.stringifyFixed(1)) * ``` * @param digits must be a non-negative integer * @returns a function that converts a Size to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Size) => string; /** * Indicates whether the given Size is equal to the current Size. * @param s - The Size to compare to the current Size. * @returns True if the Sizes have the same width and height, * false otherwise. * @see {@link equalTo} */ equals(s: Size): boolean; /** * Indicates whether the given size is equal to this Size. * @param w - the width. * @param h - the height. * @returns True if the Sizes have the same width and height, * false otherwise. * @see {@link equals} */ equalTo(w: number, h: number): boolean; /** * (undocumented) * True when the given Size is nearly equal to this Size. * @param s - The Size to compare to the current Size. * @returns True if the two Sizes have Width and Height values that * are equal with a tolerance of 0.5, false otherwise. */ equalsApprox(s: Size): boolean; /** * Modify this Size so that its width and height are changed by the given distances. * When the arguments are negative, this operation deflates this Size, but not beyond zero. * @param w - The additional width, which must be a real number; may be negative. * @param h - The additional height, which must be a real number; may be negative. * @returns this. */ inflate(w: number, h: number): Size; /** * Gets or sets the width value of the Size. * The value must not be negative. */ get width(): number; set width(value: number); /** * Gets or sets the height value of the Size. * The value must not be negative. */ get height(): number; set height(value: number); /** * True if this Size has Width and Height values that are real numbers and not infinity. */ isReal(): boolean; } /** * A Rect describes a rectangular two-dimensional area as a top-left point (x and y values) * and a size (width and height values). * * Use the static functions {@link Rect.parse} and {@link Rect.stringify} to convert to and from * a standard string representation that is independent of the current locale. * * When an instance of this class is the value of a property of a {@link GraphObject} class or {@link Diagram} * or {@link CommandHandler} or a {@link Tool} class, you should treat the object * as if it were frozen or read-only -- you cannot modify its properties. * This allows the property to return a value without allocating a new instance. * If you need to do your own calculations with the value, call {@link copy} to make * a new instance with the same values that you can modify. * * Many methods modify the object's properties and then return a reference to "this" object. * The only instance method to allocate a new object is the {@link copy} method. * The static {@link Rect.parse} method also allocates a new object. * The {@link center}, {@link position}, and {@link size} properties all allocate and return a new object. * * The "Debug" implementation of this class is significantly slower than the "Release" implementation, * mostly due to additional error checking. * * You cannot inherit from this class. * @category Geometry */ export class Rect { /** * There are four constructors: (), (Point, Point), (Point, Size), * and four numbers for (x, y, width, height). * The default constructor (no argument) results in a Rect(0,0,0,0). * @param x - Top-left Point, or x value. * @param y - Bottom-right Point or Size or y value. * @param w - Width to be used if x,y are specified; * must be non-negative. * @param h - Height to be used if x,y are specified; * must be non-negative. */ constructor(x?: Point | number, y?: Point | Size | number, w?: number, h?: number); /** * Modify this Rect with new X, Y, Width, and Height values. * @param x * @param y * @param w - the width. * @param h - the height. * @returns this. */ setTo(x: number, y: number, w: number, h: number): this; /** * Modify this Rect so that its X, Y, Width, and Height values are the same as the given Rect. * @param r - the given Rect. * @returns this. */ set(r: Rect): this; /** * Modify this Rect so that its X and Y values are the same as the given Point. * @param p - the given Point. * @returns this. */ setPoint(p: Point): this; /** * Modify this Rect so that its Width and Height values are the same as the given Size. * @param s - the given Size. * @returns this. */ setSize(s: Size): this; /** * Create a copy of this Rect, with the same values. * @virtual */ copy(): Rect; /** * This static function can be used to read in a {@link Rect} from a string that was produced by {@link Rect.stringify}. * * `go.Rect.parse("1 2 3 4")` produces the Rect `new go.Rect(1, 2, 3, 4)`. * @param str */ static parse(str: string): Rect; /** * This static function can be used to write out a {@link Rect} as a string that can be read by {@link Rect.parse}. * * `go.Rect.stringify(new go.Rect(1, 2, 3, 4))` produces the string "1 2 3 4". * @param val */ static stringify(val: Rect): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Rect's values as numbers with a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * @param digits must be a non-negative integer * @returns a function that converts a Rect to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Rect) => string; /** * Indicates whether the given Rect is equal to the current Rect. * @param r - The rectangle to compare to the current rectangle. * @returns True if the Rects are equivalent in x, y, width, * and height. * @see {@link equalTo} */ equals(r: Rect): boolean; /** * Indicates whether the given Rect is equal to the current Rect. * @param x * @param y * @param w - the width. * @param h - the height. * @returns True if the Rects are equivalent in x, y, width, and height. * @see {@link equals} */ equalTo(x: number, y: number, w: number, h: number): boolean; /** * (undocumented) * True when the given Rect is nearly equal to this Rect. * @param r - The Rect to compare to the current Rect. * @returns True if the two Rects have respective X, Y, Width, * and Height values within 0.5, false otherwise. */ equalsApprox(r: Rect): boolean; /** * Indicates whether this Rect contains the given Point. * @param p - The Point to check. * @returns True if the Point is contained within this Rect, * false otherwise. * @see {@link containsRect} * @see {@link contains} */ containsPoint(p: Point): boolean; /** * Indicates whether this Rect contains the given Rect. * @param r - The Rect to check. * @returns True if the Rect is contained within this Rect, * false otherwise. * @see {@link containsPoint} * @see {@link contains} */ containsRect(r: Rect): boolean; /** * Indicates whether this Rect contains the given Point/Rect. * @param x - The X coordinate of the Point or Rect to include in the new bounds. * @param y - The Y coordinate of the Point or Rect to include in the new bounds. * @param w - The Width of the Rect to include in the new bounds, defaults to zero. * @param h - The Height of the Rect to include in the new bounds, defaults to zero. * @returns True if the Point/Rect is contained within this Rect, * false otherwise. * @see {@link containsRect} * @see {@link containsPoint} */ contains(x: number, y: number, w?: number, h?: number): boolean; /** * Modify this Rect by shifting its values with the given DX and DY offsets. * @param dx * @param dy * @returns this. */ offset(dx: number, dy: number): this; /** * Modify this Rect so that its width and height are changed on all four sides, * equally on the left and right sides, and equally on the top and bottom sides. * When the arguments are negative, this operation deflates this Rect, but not beyond zero. * @param w - The additional width on each side, left and right; may be negative. * @param h - The additional height on each side, top and bottom; may be negative. * @returns this. * @since 2.3 * @see {@link grow} * @see {@link addMargin} * @see {@link subtractMargin} */ inflate(w: number, h: number): Rect; /** * Modify this Rect by adding the given Margin to each side of the Rect. * @param m - The Margin to add to the Rect. * @returns this bigger Rect. * @see {@link subtractMargin} * @see {@link grow} * @see {@link inflate} */ addMargin(m: Margin): Rect; /** * Modify this Rect by subtracting the given Margin from each side of the Rect. * @param m - The Margin to subtract from the Rect. * @returns this smaller Rect. * @see {@link addMargin} * @see {@link grow} * @see {@link inflate} */ subtractMargin(m: Margin): Rect; /** * Modifies this Rect by adding some distance to each side of the Rect. * @param t - the amount to move the top side upwards; may be negative. * @param r - the amount to move the right side rightwards; may be negative. * @param b - the amount to move the bottom side downwards; may be negative. * @param l - the amount to move the left side leftwards; may be negative. * @returns this modified Rect. * @see {@link inflate} * @see {@link addMargin} * @see {@link subtractMargin} */ grow(t: number, r: number, b: number, l: number): Rect; /** * Modify this Rect so that it is the intersection of this Rect and the given Rect. * @param r - Rect to intersect with. * @returns this. * @see {@link intersect} * @see {@link intersects} */ intersectRect(r: Rect): Rect; /** * Modify this Rect so that it is the intersection of this Rect and the rectangle * defined by x, y, w, h. * @param x * @param y * @param w * @param h * @returns this. * @see {@link intersectRect} * @see {@link intersects} */ intersect(x: number, y: number, w: number, h: number): Rect; /** * Determine if a given Rect is partly or wholly inside of this Rect. * @param r - Rect to test intersection with. * @returns true if there is an intersection. * @see {@link intersects} * @see {@link intersectRect} */ intersectsRect(r: Rect): boolean; /** * Determine if this Rect partly or wholly overlaps the rectangle * defined by x, y, w, h. * @param x * @param y * @param w * @param h * @returns true if there is any overlap. * @see {@link intersectsRect} * @see {@link intersect} */ intersects(x: number, y: number, w: number, h: number): boolean; /** * Modify this Rect to be exactly big enough to contain both the original Rect and the given Point. * @param p - The Point to include in the new bounds. * @returns this. * @see {@link unionRect} * @see {@link union} */ unionPoint(p: Point): Rect; /** * Modify this Rect to be exactly big enough to contain this Rect and the given Rect. * @param r - The Rect to include in the new bounds. * @returns this. * @see {@link unionPoint} * @see {@link union} */ unionRect(r: Rect): Rect; /** * Modify this Rect to be exactly big enough to contain both the original Rect and the given rectangular area. * @param x - The X coordinate of the Point or Rect to include in the new bounds. * @param y - The Y coordinate of the Point or Rect to include in the new bounds. * @param w - The Width of the Rect to include in the new bounds, defaults to zero. * @param h - The Height of the Rect to include in the new bounds, defaults to zero. * @returns this. * @see {@link unionRect} * @see {@link unionPoint} */ union(x: number, y: number, w?: number, h?: number): Rect; /** * Modify this Rect so that a given Spot is at a given (x,y) point using this Rect's size. * Return this rectangle for which the spot is at that point, without modifying the size. * * The result is meaningless if {@link Spot.isNoSpot} is true. * @param x - the point where the spot should be. * @param y - the point where the spot should be. * @param spot - a Spot; {@link Spot.isSpot} must be true. * @returns this. */ setSpot(x: number, y: number, spot: Spot): this; /** * This static function indicates whether a Rect contains the given Point/Rect. * @param rx - The X coordinate of a Rect. * @param ry - The Y coordinate of a Rect. * @param rw - The Width of a Rect. * @param rh - The Height of a Rect. * @param x - The X coordinate of the Point or Rect that might be in the bounds (RX, RY, RW, RH). * @param y - The Y coordinate of the Point or Rect that might be in the bounds (RX, RY, RW, RH). * @param w - The Width of the Rect to include in the new bounds, defaults to zero. * @param h - The Height of the Rect to include in the new bounds, defaults to zero. * @returns True if the Point/Rect is contained within this Rect, * false otherwise. */ static contains(rx: number, ry: number, rw: number, rh: number, x: number, y: number, w?: number, h?: number): boolean; /** * This static function indicates whether a Rect partly or wholly overlaps the given Rect. * @param rx - The X coordinate of a Rect. * @param ry - The Y coordinate of a Rect. * @param rw - The Width of a Rect. * @param rh - The Height of a Rect. * @param x - The X coordinate of the Point or Rect that might overlap the bounds (RX, RY, RW, RH). * @param y - The Y coordinate of the Point or Rect that might overlap the bounds (RX, RY, RW, RH). * @param w * @param h * @returns true if there is any overlap. */ static intersects(rx: number, ry: number, rw: number, rh: number, x: number, y: number, w: number, h: number): boolean; /** * This static function is true if a rectangular area is intersected by a finite straight line segment. * @param x - The X coordinate of the rectangle to check for intersection with the line segment. * @param y - The Y coordinate of the rectangle to check for intersection with the line segment. * @param w - The Width of the rectangle to check for intersection with the line segment. * @param h - The Height of the rectangle to check for intersection with the line segment. * @param p1x - The X coordinate of one end of the line segment. * @param p1y - The Y coordinate of one end of the line segment. * @param p2x - The X coordinate of other end of the line segment. * @param p2y - The Y coordinate of other end of the line segment. * @returns True if the given finite line segment intersects with the given rectangular area, false otherwise. * @since 2.2 */ static intersectsLineSegment(x: number, y: number, w: number, h: number, p1x: number, p1y: number, p2x: number, p2y: number): boolean; /** * Gets or sets the top-left x coordinate of the Rect. */ get x(): number; set x(value: number); /** * Gets or sets the top-left y coordinate of the Rect. */ get y(): number; set y(value: number); /** * Gets or sets the width of the Rect. * The value must not be negative. */ get width(): number; set width(value: number); /** * Gets or sets the height of the Rect. * The value must not be negative. */ get height(): number; set height(value: number); /** * Gets or sets the leftmost value of the Rect. * This is the same as the X value. */ get left(): number; set left(value: number); /** * Gets or sets the topmost value of the Rect. * This is the same as the Y value. */ get top(): number; set top(value: number); /** * Gets or sets the x-axis value of the right of the Rect. * This is equal to the sum of the x value and the width. */ get right(): number; set right(value: number); /** * Gets or sets the y-axis value of the bottom of the Rect. * This is equal to the sum of the y value and the height. */ get bottom(): number; set bottom(value: number); /** * Gets or sets the x- and y-axis position of the Rect as a Point. */ get position(): Point; set position(value: Point); /** * Gets or sets the width and height of the Rect as a Size. */ get size(): Size; set size(value: Size); /** * Gets or sets the Point at the center of this Rect. * Setting this property just shifts the X and Y values. */ get center(): Point; set center(value: Point); /** * Gets or sets the horizontal center X coordinate of the Rect. */ get centerX(): number; set centerX(value: number); /** * Gets or sets the vertical center Y coordinate of the Rect. */ get centerY(): number; set centerY(value: number); /** * True if this Rect has X, Y, Width, and Height values that are real numbers and not infinity. */ isReal(): boolean; /** * True if this Rect has a Width and Height of zero. */ isEmpty(): boolean; } /** * The MarginLike type is the same as `Margin | number`. * A number in place of a Margin object is treated as a uniform Margin with that thickness. */ export type MarginLike = Margin | number; /** * A Margin represents a band of space outside or inside a rectangular area, * with possibly different values on each of the four sides. * * Example uses include {@link GraphObject.margin}, {@link Panel.padding}, and {@link Diagram.padding}. * * Use the static functions {@link Margin.parse} and {@link Margin.stringify} to convert to and from * a standard string representation that is independent of the current locale. * * When an instance of this class is the value of a property of a {@link GraphObject} class or {@link Diagram} * or {@link CommandHandler} or a {@link Tool} class, you should treat the object * as if it were frozen or read-only -- you cannot modify its properties. * This allows the property to return a value without allocating a new instance. * If you need to do your own calculations with the value, call {@link copy} to make * a new instance with the same values that you can modify. * * Many methods modify the object's properties and then return a reference to "this" object. * The only instance method to allocate a new object is the {@link copy} method. * The static {@link Margin.parse} method also allocates a new object. * * The "Debug" implementation of this class is significantly slower than the "Release" implementation, * mostly due to additional error checking. * * You cannot inherit from this class. * @category Geometry */ export class Margin { /** * If zero arguments are supplied, zero is used for all four sides. * If one argument is supplied, that number is used for all four sides. * If two arguments are supplied, the top and bottom sides get the first value, * and the left and right sides get the second value. * Otherwise there must be four arguments, in the order: top, right, bottom, left. * @param t - the margin for the top side; * if not supplied, all sides are zero. * @param r - the margin for the right side; * if not supplied, all sides have the value of the first argument. * @param b - the margin for all bottom side; * if not supplied, the top and bottom get the value of the first argument, * and the right and left sides get the value of the second argument. * @param l - the margin for the left side; * must be supplied if the third argument was supplied. */ constructor(t?: number, r?: number, b?: number, l?: number); /** * Modify this Margin with new Top, Right, Bottom, and Left values. * @param t - top. * @param r - right. * @param b - bottom. * @param l - left. * @returns this. */ setTo(t: number, r: number, b: number, l: number): this; /** * Modify this Margin so that its Top, Right, Bottom, and Left values * are the same as the given Margin. * @param m - the given Margin. * @returns this. */ set(m: Margin): this; /** * Create a copy of this Margin, with the same values. * @virtual */ copy(): Margin; /** * This static function can be used to read in a {@link Margin} from a string that was produced by {@link Margin.stringify}. * * `go.Margin.parse("1 2 3 4")` produces the Margin `new go.Margin(1, 2, 3, 4)`. * @param str */ static parse(str: string): Margin; /** * This static function can be used to write out a {@link Margin} as a string that can be read by {@link Margin.parse}. * * `go.Margin.stringify(new go.Margin(1, 2, 3, 4))` produces the string "1 2 3 4". * @param val */ static stringify(val: Margin): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Margin's values as numbers with a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * * Example: * ```js * new go.Binding("margin", "margin", go.Margin.parse, go.Margin.stringifyFixed(0)) * ``` * @param digits must be a non-negative integer * @returns a function that converts a Margin to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Margin) => string; /** * Indicates whether the given Margin is equal to this Margin. * @param m - The Margin to compare to this Margin. * @returns True if the two Margins have identical Top and Right and Bottom and Left values, * false otherwise. * @see {@link equalTo} */ equals(m: Margin): boolean; /** * Indicates whether the given margin is equal to this Margin. * @param t - top. * @param r - right. * @param b - bottom. * @param l - left. * @returns True if the two Margins have identical Top and Right and Bottom and Left values, * false otherwise. * @see {@link equals} */ equalTo(t: number, r: number, b: number, l: number): boolean; /** * (undocumented) * True when the given Margin is nearly equal to this Margin. * @param m - The Margin to compare to the current Margin. * @returns True if the two Margins have Top, Right, * Bottom and Left values within 0.5, false otherwise. */ equalsApprox(m: Margin): boolean; /** * Gets or sets the top value of this margin. Default is 0. */ get top(): number; set top(value: number); /** * Gets or sets the right value of this margin. Default is 0. */ get right(): number; set right(value: number); /** * Gets or sets the bottom value of this margin. Default is 0. */ get bottom(): number; set bottom(value: number); /** * Gets or sets the left value of this margin. Default is 0. */ get left(): number; set left(value: number); /** * True if this Margin has values that are real numbers and not infinity. */ isReal(): boolean; } /** * A Spot represents a relative point from (0,0) to (1,1) within the bounds of * a rectangular area plus an absolute offset. * * Use the static functions {@link Spot.parse} and {@link Spot.stringify} to convert to and from * a standard string representation that is independent of the current locale. * * When an instance of this class is the value of a property of a {@link GraphObject} class or {@link Diagram} * or {@link CommandHandler} or a {@link Tool} class, you should treat the object * as if it were frozen or read-only -- you cannot modify its properties. * This allows the property to return a value without allocating a new instance. * If you need to do your own calculations with the value, call {@link copy} to make * a new instance with the same values that you can modify. * * Many methods modify the object's properties and then return a reference to "this" object. * The only instance method to allocate a new object is the {@link copy} method. * The static {@link Spot.parse} method also allocates a new object. * * The "Debug" implementation of this class is significantly slower than the "Release" implementation, * mostly due to additional error checking. * * You cannot inherit from this class. * @category Geometry */ export class Spot { /** * The default constructor produces the Spot(0, 0, 0, 0), at the top-left corner. * @param x - The x value of the Spot. Default is zero. * @param y - The y value of the Spot. Default is zero. * @param offx - (Optional) The absolute x offset. Default is zero. * @param offy - (Optional) The absolute y offset. Default is zero. */ constructor(x?: number, y?: number, offx?: number, offy?: number); /** * Modify this Spot with new X, Y, OffsetX, and OffsetY values. * @param x * @param y * @param offx * @param offy * @returns this. */ setTo(x: number, y: number, offx: number, offy: number): this; /** * Modify this Spot so that its X, Y, OffsetX, and OffsetY values are the same as the given Spot. * @param s - the given Spot. * @returns this. */ set(s: Spot): this; /** * Create a copy of this Spot, with the same values. * @virtual */ copy(): Spot; /** * This static function can be used to read in a {@link Spot} from a string that was produced by {@link Spot.stringify}. * * `go.Spot.parse("0 1 2 3")` produces the Spot `new go.Spot(0, 1, 2, 3)`. * @param str */ static parse(str: string): Spot; /** * This static function can be used to write out a {@link Spot} as a string that can be read by {@link Spot.parse}. * * `go.Spot.stringify(new go.Spot(0, 1, 2, 3))` produces the string "0 1 2 3". * @param val */ static stringify(val: Spot): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Spot's values as numbers with a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * @param digits must be a non-negative integer * @returns a function that converts a Spot to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Spot) => string; /** * Two spots are equal if all four property values are the same. * @param spot - The Spot to compare to the current Spot. * @returns True if the two spots are equal, false otherwise. */ equals(spot: Spot): boolean; /** * Return a new spot that is opposite this spot. * The X and Y values will be an equal distance * away from the center on the other side of the center. * The OffsetX and OffsetY values are also negated. * * The result is meaningless if {@link isNoSpot} is true. */ opposite(): Spot; /** * This predicate is true if this Spot is a side that * includes the side(s) given by the argument Spot. * @param side * @returns false if either this Spot or the argument Spot is not a "Side"; * true if the side(s) that this Spot represents are a superset or the same set of * sides represented by the argument Spot. */ includesSide(side: Spot): boolean; /** * Gets or sets the x value of the Spot, a fractional value between zero and one. * * The Spot(0,0) of a rectangle is at the top-left corner. * This value is commonly available as {@link Spot.TopLeft}. * The Spot(0.5,1) would be at the middle of the bottom side. * That value is commonly available as {@link Spot.MiddleBottom}. */ get x(): number; set x(value: number); /** * Gets or sets the y value of the Spot, a fractional value between zero and one. * * The Spot(0,1) of a rectangle is at the bottom-left corner. * This value is commonly available as {@link Spot.BottomLeft}. * The Spot(1,0.5) would be at the middle of the right side. * That value is commonly available as {@link Spot.MiddleRight}. */ get y(): number; set y(value: number); /** * Gets or sets the offsetX value of the Spot. * The value may be negative. * If this represents a side value instead of a specific spot, this value is meaningless. * * A Spot(0,0,5,5) of a large rectangle is near the top-left corner, inside the rectangle. * A Spot(1,1,5,5) would be near the bottom-right corner, outside the rectangle. * A Spot(1,1,-5,-5) would also be near the bottom-right corner, but inside the rectangle. */ get offsetX(): number; set offsetX(value: number); /** * Gets or sets the offsetY value of the Spot. * The value may be negative. * If this represents a side value instead of a specific spot, this value is meaningless. * * A Spot(0,0,5,5) of a large rectangle is near the top-left corner, inside the rectangle. * A Spot(1,1,5,5) would be near the bottom-right corner, outside the rectangle. * A Spot(1,1,-5,-5) would also be near the bottom-right corner, but inside the rectangle. */ get offsetY(): number; set offsetY(value: number); /** * True if this is a specific spot, not a side nor {@link Spot.None}. */ isSpot(): boolean; /** * True if this is an unspecific special spot, such as {@link Spot.None} * or one of the sides. */ isNoSpot(): boolean; /** * True if this is a special spot referring to one (or more) of the sides. * This is false if the spot is {@link Spot.None}. */ isSide(): boolean; /** * True if this is a special spot referring to no particular spot or side. */ isNone(): boolean; /** * True if this is a special spot indicating that the real spot value will come from another source. */ isDefault(): boolean; /** * Use this Spot value to indicate no particular spot -- * code looking for a particular point on an element will need to do their * own calculations to determine the desired point depending on the * circumstances. * @constant */ static readonly None: Spot; /** * Use this value to indicate that the real spot value is inherited from elsewhere. * @constant */ static readonly Default: Spot; /** * The specific point at the top-left corner of the bounding rectangle. * @constant */ static readonly TopLeft: Spot; /** * The specific point at the center of the top side of the bounding rectangle. * @constant */ static readonly TopCenter: Spot; /** * The specific point at the top-right corner of the bounding rectangle. * @constant */ static readonly TopRight: Spot; /** * The specific point at the middle of the left side of bounding rectangle. * @constant */ static readonly LeftCenter: Spot; /** * The specific point at the very center of the bounding rectangle. * @constant */ static readonly Center: Spot; /** * The specific point at the middle of the right side of bounding rectangle. * @constant */ static readonly RightCenter: Spot; /** * The specific point at the bottom-left corner of the bounding rectangle. * @constant */ static readonly BottomLeft: Spot; /** * The specific point at the middle of the bottom side of bounding rectangle. * @constant */ static readonly BottomCenter: Spot; /** * The specific point at the bottom-right corner of the bounding rectangle. * @constant */ static readonly BottomRight: Spot; /** * A synonym for {@link Spot.TopCenter}. * @constant */ static readonly MiddleTop: Spot; /** * A synonym for {@link Spot.LeftCenter}. * @constant */ static readonly MiddleLeft: Spot; /** * A synonym for {@link Spot.RightCenter}. * @constant */ static readonly MiddleRight: Spot; /** * A synonym for {@link Spot.BottomCenter}. * @constant */ static readonly MiddleBottom: Spot; /** * A synonym for {@link Spot.TopCenter}. * @constant */ static readonly Top: Spot; /** * A synonym for {@link Spot.LeftCenter}. * @constant */ static readonly Left: Spot; /** * A synonym for {@link Spot.RightCenter}. * @constant */ static readonly Right: Spot; /** * A synonym for {@link Spot.BottomCenter}. * @constant */ static readonly Bottom: Spot; /** * The set of points at the top side of the bounding rectangle. * @constant */ static readonly TopSide: Spot; /** * The set of points at the left side of the bounding rectangle. * @constant */ static readonly LeftSide: Spot; /** * The set of points at the right side of the bounding rectangle. * @constant */ static readonly RightSide: Spot; /** * The set of points at the bottom side of the bounding rectangle. * @constant */ static readonly BottomSide: Spot; /** * The set of points at the top or bottom sides of the bounding rectangle. * @constant */ static readonly TopBottomSides: Spot; /** * The set of points at the left or right sides of the bounding rectangle. * @constant */ static readonly LeftRightSides: Spot; /** * The set of points at the top or left sides of the bounding rectangle. * @constant */ static readonly TopLeftSides: Spot; /** * The set of points at the top or right sides of the bounding rectangle. * @constant */ static readonly TopRightSides: Spot; /** * The set of points at the left or bottom sides of the bounding rectangle. * @constant */ static readonly BottomLeftSides: Spot; /** * The set of points at the right or bottom sides of the bounding rectangle. * @constant */ static readonly BottomRightSides: Spot; /** * The set of points on all sides of the bounding rectangle except top side. * @constant */ static readonly NotTopSide: Spot; /** * The set of points on all sides of the bounding rectangle except left side. * @constant */ static readonly NotLeftSide: Spot; /** * The set of points on all sides of the bounding rectangle except right side. * @constant */ static readonly NotRightSide: Spot; /** * The set of points on all sides of bounding rectangle except bottom side. * @constant */ static readonly NotBottomSide: Spot; /** * The set of points on all sides of the bounding rectangle. * @constant */ static readonly AllSides: Spot; } /** * This enumeration specifies possible values for {@link Geometry.type}. * @since 3.0 * @category Geometry */ export declare enum GeometryType { /** * For drawing a simple straight line. * * The line goes from the point ({@link Geometry.startX}, {@link Geometry.startY}) * to the point ({@link Geometry.endX}, {@link Geometry.endY}). */ Line = 1, /** * For drawing a rectangle. * * The rectangle goes from the point from the point ({@link Geometry.startX}, {@link Geometry.startY}) * to the point ({@link Geometry.endX}, {@link Geometry.endY}). */ Rectangle = 2, /** * For drawing an ellipse fitting within a rectangle. * * The ellipse fits within the rectangle that goes from the point ({@link Geometry.startX}, {@link Geometry.startY}) * to the point ({@link Geometry.endX}, {@link Geometry.endY}). */ Ellipse = 3, /** * For drawing a complex path made of a list of {@link PathFigure}s */ Path = 4 } /** * This enumeration specifies possible values for {@link Shape.geometryStretch} and {@link Geometry.defaultStretch}. * @since 3.0 * @category Geometry */ export declare enum GeometryStretch { /** * Do not scale the geometry; there may be clipping in one or both directions if the available dimensions are too small. */ None = 0, /** * Scale the geometry depending on context, for instance uniformly for a "Circle" figure and non-uniformly for an "Ellipse" figure. */ Default = 1, /** * Scale the geometry in both directions so as to fit exactly in the given bounds; * there is no clipping, but the aspect ratio may change, causing the geometry to appear stretched. */ Fill = 2, /** * Scale the geometry equally in both directions to fit the given bounds. */ Uniform = 6 } /** * The Geometry class is used to define the "shape" of a {@link Shape}. * A Geometry can be simple straight lines, rectangles, or ellipses. * A Geometry can also be an arbitrarily complex path, consisting of a list of {@link PathFigure}s. * * A Geometry must not be modified once it has been used by a {@link Shape}. * However, a Geometry may be shared by multiple Shapes. * * It is commonplace to create Geometries using geometry path string syntax: * Geometry Path Strings. * However it is much more efficient to create Geometries programmatically. * One way to do that is illustrated by several of the samples that evaluate JavaScript such as: * ```js * new go.Geometry() * .add(new go.PathFigure(p.x, p.y) * .add(new go.PathSegment(go.SegmentType.Arc, -sweep/2, sweep, 0, 0, radius+layerThickness, radius+layerThickness)) * .add(new go.PathSegment(go.SegmentType.Line, q.x, q.y)) * .add(new go.PathSegment(go.SegmentType.Arc, sweep/2, -sweep, 0, 0, radius, radius).close())); * ``` * See samples that make use of Geometries in the samples index. * @category Geometry */ export class Geometry { /** * @param type * Construct an empty Geometry. * The geometry type must be a {@link GeometryType}. * The default type is {@link GeometryType.Path}. */ constructor(type?: GeometryType); /** * Create a copy of this Geometry, with the same values and figures. * @virtual */ copy(): Geometry; /** * @deprecated See {@link GeometryType.Line}. */ static readonly Line = GeometryType.Line; /** * @deprecated See {@link GeometryType.Rectangle}. */ static readonly Rectangle = GeometryType.Rectangle; /** * @deprecated See {@link GeometryType.Ellipse}. */ static readonly Ellipse = GeometryType.Ellipse; /** * @deprecated See {@link GeometryType.Path}. */ static readonly Path = GeometryType.Path; /** * (undocumented) * @param g */ equalsApprox(g: Geometry): boolean; /** * This static function can be used to write out a {@link Geometry} as a string * that can be read by {@link Geometry.parse}. * * The string produced by this method is a superset of the SVG path * string rules that contains some additional GoJS-specific tokens. * See the Introduction page on Geometry Parsing for more details. * @param val a Geometry to be rendered as a string */ static stringify(val: Geometry): string; /** * This static function returns a function that can be used as a back converter for a Binding * to write out a Geometry as a string with its numbers at a fixed number of digits after the decimal point. * * This is useful for limiting the size of JSON output and making it more legible. * It might also be useful for regression testing. * @param digits must be a non-negative integer * @returns a function that converts a Geometry to a string without so many decimals * @since 3.0 */ static stringifyFixed(digits: number): (val: Geometry) => string; /** * Given a SVG or GoJS path string, returns a congruent path string with each pathfigure filled. * For instance, "M0 0 L22 22 L33 0" would become "F M0 0 L22 22 L33 0". * @param str */ static fillPath(str: string): string; /** * Produce a {@link Geometry} from a string that uses an SVG-like compact path geometry syntax. * The syntax accepts all SVG Path Syntax (SVG Path Syntax (w3.org)), * as well as three GoJS-specific tokens. * Specifically, the following tokens are allowed: * - `M (x,y)+ ` - Move commands * - `L (x,y)+, H (x)+, V (y)+` Lines commands, including horizontal and vertical lines * - `C (x1 y1 x2 y2 x y)+, S (x2 y2 x y)+` Cubic bezier curves * - `Q (x1 y1 x y)+, T (x y)+` Quadratic bezier curves * - `A (rx ry x-axis-rotation large-arc-flag clockwise-flag x y)+` Arcs (following SVG arc conventions) * - `Z` Denotes that the previous subpath is closed * * Additionally there are some tokens specific to GoJS: * - `B (startAngle, sweepAngle, centerX, centerY, radius)+` Arcs following GoJS canvas arc conventions * - `X` Used before M-commands to denote separate PathFigures instead of a subpath * - `F` Denotes whether the current PathFigure is filled (true if F is present) * - `F0` (instead of `F`) Denotes that the PathFigure should use the even-odd fill rule instead of the nonzero winding number rule (setting {@link PathFigure.isEvenOdd}) * - `U` Denotes that the PathFigure is not shadowed * * See the Introduction page on Geometry Parsing for more details. * @param str * @param filled - whether figures should be filled. * If true, all PathFigures in the string will be filled regardless of the presence * of an "F" command or not. * If false, all PathFigures will determine their own filled state by the presence of an "F" command or not. * Default is false. */ static parse(str: string, filled?: boolean): Geometry; /** * Computes the Geometry's bounds without adding an origin point, and returns those bounds as a rect. * This method does not modify the Geometry or its bounds. */ computeBoundsWithoutOrigin(): Rect; /** * Normalizes the Geometry points in place by ensuring the top-left bounds of the geometry lines up with (0, 0), * returning the {@link Point} (x, y) amount it was shifted. * After this method is called there will be no negative X or Y value for the Geometry's bounds, * and no empty space at the top-left of the Geometry. */ normalize(): Point; /** * Offsets the Geometry in place by a given (x, y) amount * @param x - The x-axis offset factor. * @param y - The y-axis offset factor. * @returns this */ offset(x: number, y: number): this; /** * Scales the Geometry in place by a given (x, y) scale factor. * * If you want to flip a Geometry horizontally, call `geo.scale(-1, 1)`. * If you want to flip a Geometry vertically, call `geo.scale(1, -1)`. * @param x - The x-axis scale factor. * @param y - The y-axis scale factor. * @returns this */ scale(x: number, y: number): this; /** * Rotates the Geometry in place by a given angle, with optional x and y values to rotate the geometry about. * If no x and y value are given, (0, 0) is used as the rotation point. * @param angle - The angle to rotate by. * @param x - The optional X point to rotate the geometry about. If no point is given, this value is 0. * @param y - The optional Y point to rotate the geometry about. If no point is given, this value is 0. * @returns this */ rotate(angle: number, x?: number, y?: number): this; /** * Returns true if the Geometry contains the point. * @param p - in local geometry coordinates * @param sw - half the stroke width that a Shape has or that you want to pretend it has * @since 2.2 */ containsPoint(p: Point, sw?: number): boolean; /** * Returns the point at the fractional distance (0-1) along this Geometry's path. * @param fraction - A fractional amount between 0 and 1, inclusive. * @param result - an optional Point that is modified and returned; otherwise it allocates and returns a new Point. * @returns the Point, in local coordinates, of the fractional distance along the path. * @since 2.1 */ getPointAlongPath(fraction: number, result?: Point): Point; /** * Returns the slope expressed as an angle at the fractional distance (0-1) along this Geometry's path, in local coordinates. * @param fraction - A fractional amount between 0 and 1, inclusive. * @since 2.1 */ getAngleAlongPath(fraction: number): number; /** * Returns the fractional distance (0-1) along this Geometry's path for a nearby point. * @param pt - A Point, in local coordinates, near this Geometry. * @returns A fractional amount between 0 and 1, inclusive. * @since 2.1 */ getFractionForPoint(pt: Point): number; /** * (undocumented) * Flattened segments represents a series of points making up a Geometry. * The inner arrays consist of a sequence of PathSegment coordinates making up a PathFigure, * while the outer array represents the whole Geometry of these PathFigures. */ get flattenedSegments(): Array>; /** * (undocumented) * Flattened lengths represents a series of lengths of the paths making up a Geometry. * The inner arrays consist of a sequence of PathSegment lengths making up a PathFigure, * while the outer array represents the whole Geometry of these PathFigures. */ get flattenedLengths(): Array>; /** * (undocumented) * This read-only property returns the approximate length of the path. * This is the overall distance of all the PathSegments that make up the geometry. */ get flattenedTotalLength(): number; /** * Gets or sets the type of the Geometry. * The default type is {@link GeometryType.Path}. */ get type(): GeometryType; set type(value: GeometryType); /** * Gets or sets the starting X coordinate of the Geometry if it is of type * {@link GeometryType.Line|Line}, {@link GeometryType.Rectangle|Rectangle}, or {@link GeometryType.Ellipse|Ellipse}. * The initial value is zero. */ get startX(): number; set startX(value: number); /** * Gets or sets the starting Y coordinate of the Geometry if it is of type * {@link GeometryType.Line|Line}, {@link GeometryType.Rectangle|Rectangle}, or {@link GeometryType.Ellipse|Ellipse}. * The initial value is zero. */ get startY(): number; set startY(value: number); /** * Gets or sets the ending X coordinate of the Geometry if it is of type * {@link GeometryType.Line|Line}, {@link GeometryType.Rectangle|Rectangle}, or {@link GeometryType.Ellipse|Ellipse}. * The initial value is zero. */ get endX(): number; set endX(value: number); /** * Gets or sets the ending Y coordinate of the Geometry if it is of type * {@link GeometryType.Line|Line}, {@link GeometryType.Rectangle|Rectangle}, or {@link GeometryType.Ellipse|Ellipse}. * The initial value is zero. */ get endY(): number; set endY(value: number); /** * Gets or sets the {@link List} of {@link PathFigure}s * that describes the content of the * path for Geometries of type {@link GeometryType.Path|Path}. */ get figures(): List; set figures(value: List); /** * Add a {@link PathFigure} to the {@link figures} list. * @param figure - a newly allocated unshared PathFigure that will become owned by this Geometry * @returns this */ add(figure: PathFigure): this; /** * (undocumented) * Set {@link spot1} and {@link spot2} without allocating new {@link Spot}s. * @param f1x - spot1.x * @param f1y - spot1.y * @param f2x - spot2.x * @param f2y - spot2.y * @param o1x - offset1.x, default is zero * @param o1y - offset1.y, default is zero * @param o2x - offset2.x, default is zero * @param o2y - offset2.y, default is zero * @returns this */ setSpots(f1x: number, f1y: number, f2x: number, f2y: number, o1x?: number, o1y?: number, o2x?: number, o2y?: number): this; /** * Gets or sets the spot an "Auto" {@link Panel} will use for the top-left corner of any panel content * when the {@link Shape.spot1} value is {@link Spot.Default}. * The default value is {@link Spot.TopLeft}, at the top-left point of the bounds of the Shape. */ get spot1(): Spot; set spot1(value: Spot); /** * Gets or sets the spot an "Auto" {@link Panel} will use for the bottom-right corner of any panel content * when the {@link Shape.spot2} value is {@link Spot.Default}. * The default value is {@link Spot.BottomRight}, at the bottom-right point of the bounds of the Shape. */ get spot2(): Spot; set spot2(value: Spot); /** * Gets or sets the {@link Shape.geometryStretch} value the {@link Shape} should use by default * when the {@link Shape.geometryStretch} value is {@link GeometryStretch.None}. * The default value is {@link GeometryStretch.Fill}. * Some figure generators return a Geometry with this property set to {@link GeometryStretch.Uniform}, * in order to preserve its aspect ratio when used by a Shape that may have different sizes. */ get defaultStretch(): GeometryStretch; set defaultStretch(value: GeometryStretch); /** * This read-only property returns a rectangle that contains all points within the Geometry. * The result will always contain the origin (0, 0). */ get bounds(): Rect; } /** * A PathFigure represents a section of a {@link Geometry}. * It is a single connected series of * two-dimensional geometric {@link PathSegment}s. * * The {@link Geometry.figures} property is a list of PathFigures. * * PathFigures are drawn with the {@link Shape.stroke} and other stroke properties. * Filled PathFigures are painted with the {@link Shape.fill}. * * A PathFigure must not be modified once its containing {@link Geometry} * has been assigned to a {@link Shape}. * @category Geometry */ export class PathFigure { /** * Constructs an empty figure. * The optional arguments specify the starting point of the figure. * You'll want to add a new instance of a PathFigure to the * {@link Geometry.figures} list of a {@link Geometry}. * @param sx - optional: the X coordinate of the start point (default is zero). * @param sy - optional: the Y coordinate of the start point (default is zero). * @param filled - optional: whether the figure is filled (default is true). * @param shadowed - optional: whether the figure may be drawn with a shadow (default is true). * @param isEvenOdd - optional: whether uses the even-odd rule (true) or nonzero winding number rule (the default, false). */ constructor(sx?: number, sy?: number, filled?: boolean, shadowed?: boolean, isEvenOdd?: boolean); /** * Create a copy of this PathFigure, with the same values and segments. * @virtual */ copy(): PathFigure; /** * (undocumented) * @param f */ equalsApprox(f: PathFigure): boolean; /** * Gets or sets whether this PathFigure is drawn filled. * The default value is true. */ get isFilled(): boolean; set isFilled(value: boolean); /** * Gets or sets whether this PathFigure will render a shadow if one is defined. * This is used for turning off shadows on specific subpaths. * The default value is true. */ get isShadowed(): boolean; set isShadowed(value: boolean); /** * Gets or sets whether this PathFigure will render and hit-test with the even-odd fill rule * or nonzero winding number fill rule (false). * The default value is false, using the nonzero winding number rule. * * In Geometry Path Strings, this is set by using "F0" instead of "F" at the beginning of a figure. * @since 2.3 */ get isEvenOdd(): boolean; set isEvenOdd(value: boolean); /** * Gets or sets the starting point X coordinate of the PathFigure. * The default value is zero. */ get startX(): number; set startX(value: number); /** * Gets or sets the starting point Y coordinate of the PathFigure. * The default value is zero. */ get startY(): number; set startY(value: number); /** * Gets or sets the {@link List} of {@link PathSegment}s that define this PathFigure. */ get segments(): List; set segments(value: List); /** * Add a {@link PathSegment} to the {@link segments} list. * @param segment - a newly allocated unshared PathSegment that will become owned by this PathFigure */ add(segment: PathSegment): this; } /** * This enumeration specifies possible values for {@link PathSegment.type}. * @since 3.0 * @category Geometry */ export declare enum SegmentType { /** * For beginning a new subpath. */ Move = 1, /** * For drawing a straight line segment. */ Line = 2, /** * For drawing a cubic bezier segment. */ Bezier = 3, /** * For drawing a quadratic bezier segment. */ QuadraticBezier = 4, /** * For drawing an arc segment. */ Arc = 5, /** * For drawing an SVG arc segment. * * See: SVG Arc specification (w3.org) */ SvgArc = 6 } /** * A PathSegment represents a straight line or curved segment of a path between * two or more points that are part of a {@link PathFigure}. * The very first point is given by the {@link PathFigure.startX} and {@link PathFigure.startY} properties. * After the first segment the beginning point of the next segment is the same as the end point of the previous segment. * For most types of PathSegments the end point of the segment is given by {@link endX} and {@link endY}. * * A PathSegment must not be modified once its containing {@link PathFigure}'s * {@link Geometry} has been assigned to a {@link Shape}. * @category Geometry */ export class PathSegment { /** * Constructs a segment that goes nowhere unless you specify some Points. * * The very first point of a path is specified in the containing {@link PathFigure} by * its {@link PathFigure.startX} and {@link PathFigure.startY} properties. * * The segment type must be a {@link SegmentType}. * You will want to add a new instance of a PathSegment to the * {@link PathFigure.segments} list of a {@link PathFigure}. * @param type - if not supplied, the default PathSegment type is {@link SegmentType.Line}. * But if the type is supplied, one must also provide the endpoint X and Y values, * either as arguments in this constructor or by setting the {@link endX} and {@link endY} properties. * If the type is QuadraticBezier, the X1 and Y1 control point values must both be supplied. * If the type is Bezier, X1, Y1, X2, and Y2 control point values must all be supplied. * * If the type is {@link SegmentType.Line|Line} it needs the following arguments: * * `(go.SegmentType.Line, ex, ey)` * - **ex, ey** describe the end point * * If the type is {@link SegmentType.QuadraticBezier|QuadraticBezier} it needs the following arguments: * * `(go.SegmentType.QuadraticBezier, ex, ey, x1, y1)` * - **ex, ey** describe the end point * - **x1, y1** describe the only control point * * If the type is {@link SegmentType.Bezier|Bezier} it needs the following arguments: * * `(go.SegmentType.Bezier, ex, ey, x1, y1, x2, y2)` * - **ex, ey** describe the end point * - **x1, y1** describe the first control point * - **x2, y2** describe the second control point * * If the type is {@link SegmentType.Arc|Arc} it needs the following arguments: * * `(go.SegmentType.Arc, startAngle, sweepAngle, centerX, centerY, radiusX, radiusY)` * - **startAngle** describes the start angle, in degrees * - **sweepAngle** describes the sweep angle, in degrees * - **centerX, centerY** describe the center point * - **radiusX, radiusY** describe the radiusX and radiusY * * If the type is {@link SegmentType.SvgArc|SvgArc} it needs the following arguments: * * `(go.SegmentType.SvgArc, ex, ey, radiusX, radiusY, xAxisRotation, largeArcFlag, clockwiseFlag)` * * They are in the same order as arcs in SVG path strings, except the endpoint x and y values come first, not last. * - **ex, ey** describe the endpoint * - **radiusX, radiusY** describe the radius * - **xAxisRotation** describes the {@link xAxisRotation} (number in degrees) * - **largeArcFlag** describes the {@link isLargeArc} (true or false) * - **clockwiseFlag** describes the {@link isClockwiseArc} (true or false). * * If the type is {@link SegmentType.Move|Move} it needs the following arguments: * * `(go.SegmentType.Move, ex, ey)` * - **ex, ey** describe the next starting point * * @param ex - optional: the X coordinate of the end point, or the startAngle of an Arc. * @param ey - optional: the Y coordinate of the end point, or the sweepAngle of an Arc. * @param x1 - optional: the X coordinate of the first bezier control point, or the centerX of an Arc, or the radiusX of an SvgArc. * @param y1 - optional: the Y coordinate of the first bezier control point, or the centerY of an Arc, or the radiusY of an SvgArc. * @param x2 - optional: the X coordinate of the second cubic bezier control point, or the radiusX of an Arc, or the xAxisRotation of an SvgArc. * @param y2 - optional: the Y coordinate of the second cubic bezier control point, or the radiusY of an Arc, or whether this is the larger arc of an SvgArc. * @param clockwise - optional: whether an SvgArc goes clockwise or counterclockwise. */ constructor(type?: SegmentType, ex?: number, ey?: number, x1?: number, y1?: number, x2?: number, y2?: number | boolean, clockwise?: boolean); /** * Create a copy of this PathSegment, of the same type and with the same point values. * @virtual */ copy(): PathSegment; /** * (undocumented) * @param s */ equalsApprox(s: PathSegment): boolean; /** * @deprecated See {@link SegmentType.Move}. */ static readonly Move = SegmentType.Move; /** * @deprecated See {@link SegmentType.Line}. */ static readonly Line = SegmentType.Line; /** * @deprecated See {@link SegmentType.Bezier}. */ static readonly Bezier = SegmentType.Bezier; /** * @deprecated See {@link SegmentType.QuadraticBezier}. */ static readonly QuadraticBezier = SegmentType.QuadraticBezier; /** * @deprecated See {@link SegmentType.Arc}. */ static readonly Arc = SegmentType.Arc; /** * @deprecated See {@link SegmentType.SvgArc}. */ static readonly SvgArc = SegmentType.SvgArc; /** * Closes the path after this PathSegment * @returns returns this PathSegment. */ close(): this; /** * Gets or sets whether the path is closed after this PathSegment. * Default value is false. */ get isClosed(): boolean; set isClosed(value: boolean); /** * Gets or sets the type of the PathSegment. * The value must be a {@link SegmentType}. */ get type(): SegmentType; set type(value: SegmentType); /** * Gets or sets the X coordinate of the end point for all types of PathSegment except {@link SegmentType.Arc|Arc}. * The default value is zero. */ get endX(): number; set endX(value: number); /** * Gets or sets the Y coordinate of the end point for all types of PathSegment except {@link SegmentType.Arc|Arc}. * The default value is zero. */ get endY(): number; set endY(value: number); /** * Gets or sets the X value of the first control point for a PathSegment * of type {@link SegmentType.Bezier|Bezier} or {@link SegmentType.QuadraticBezier|QuadraticBezier}. */ get point1X(): number; set point1X(value: number); /** * Gets or sets the Y value of the first control point for a PathSegment * of type {@link SegmentType.Bezier|Bezier} or {@link SegmentType.QuadraticBezier|QuadraticBezier}. */ get point1Y(): number; set point1Y(value: number); /** * Gets or sets the X value of the second control point for a PathSegment * of type cubic {@link SegmentType.Bezier|Bezier}. */ get point2X(): number; set point2X(value: number); /** * Gets or sets the Y value of the second control point for a PathSegment * of type cubic {@link SegmentType.Bezier|Bezier}. */ get point2Y(): number; set point2Y(value: number); /** * Gets or sets the center X value of the Arc for a PathSegment of type {@link SegmentType.Arc|Arc}. */ get centerX(): number; set centerX(value: number); /** * Gets or sets the center Y value of the Arc for a PathSegment of type {@link SegmentType.Arc|Arc}. */ get centerY(): number; set centerY(value: number); /** * Gets or sets the X value of the radius for a PathSegment of type {@link SegmentType.Arc|Arc} or {@link SegmentType.SvgArc|SvgArc}. * Value must be a positive number. */ get radiusX(): number; set radiusX(value: number); /** * Gets or sets the Y value of the radius for a PathSegment of type {@link SegmentType.Arc|Arc} or {@link SegmentType.SvgArc|SvgArc}. * Value must be a positive number. */ get radiusY(): number; set radiusY(value: number); /** * Gets or sets the starting angle for a PathSegment of type {@link SegmentType.Arc|Arc}. * Value must within the range: (0 <= value < 360). */ get startAngle(): number; set startAngle(value: number); /** * Gets or sets the length of angle in degrees, or amount of arc to "sweep" for a PathSegment of type {@link SegmentType.Arc|Arc}. * Must be between -360 and 360, inclusive. */ get sweepAngle(): number; set sweepAngle(value: number); /** * Gets or sets the clockwise-flag for a PathSegment of type {@link SegmentType.SvgArc|SvgArc}. * SVG Arcs specify a radius and an endpoint, and are always a portion of an ellipse. * The parameters allow for two potential ellipses and four potential arcs. * A clockwise-flag set to true will use one of the two possible positive-angle arcs, * and false will use one of the two negative-angle arcs. Which arc is chosen (small or large) * depends on the value of {@link isLargeArc}. * For more information see the visual examples in the * SVG Arc specification (w3.org) */ get isClockwiseArc(): boolean; set isClockwiseArc(value: boolean); /** * Gets or sets the large-arc-flag for a PathSegment of type {@link SegmentType.SvgArc|SvgArc}. * SVG Arcs specify a radius and an endpoint, and are always a portion of an ellipse. * The parameters allow for two potential ellipses and four potential arcs. * A large-arc-flag set to true will choose the larger of the two arc sweeps. * Which way the arc sweeps (positive angle or negative angle) depends on the value of {@link isClockwiseArc} * For more information see the visual examples in the * SVG Arc specification (w3.org) */ get isLargeArc(): boolean; set isLargeArc(value: boolean); /** * Gets or sets the X-axis rotation for a PathSegment of type {@link SegmentType.SvgArc|SvgArc}. * X-axis rotation is used to rotate the ellipse that the arc is created from, * and must be between 0 and 360 degrees. * Default is 0. */ get xAxisRotation(): number; set xAxisRotation(value: number); } /** * An InputEvent represents a mouse or keyboard or touch event. * The principal properties hold information about a particular input event. * These properties include the {@link documentPoint} at which a mouse event * occurred in document coordinates, * the corresponding point in view/element coordinates, {@link viewPoint}, * the {@link key} and {@link code} for keyboard events, * and the {@link modifiers} and {@link button} at the time. * Additional descriptive properties include {@link clickCount}, {@link delta}, * {@link timestamp}, and the source event {@link event} (if available). * * Many of its properties are provided for convenient access to the state of the input event, * such as asking whether the {@link control} key was held down at the time, * or the {@link targetObject} (a {@link GraphObject}) that the mouse was over. * KeyboardEvent keys across languages are normalized for use in Tools and Commands via {@link commandKey}. * * When real events fire on the Diagram, InputEvents are created automatically set update the value of {@link Diagram.lastInput}. * These events set the value of {@link event} with the backing browser-defined Event, * which may be a MouseEvent, KeyboardEvent, PointerEvent, and so on. * * InputEvents backed by MouseEvents set both {@link button}, the button that caused the action, * and {@link buttons}, the set of buttons currently pressed after the action has happened. * By default a user-created InputEvent sets {@link button} and {@link buttons} as if the event was a left-click. * * You can create InputEvents and set the value of {@link Diagram.lastInput} in order to simulate user actions in tools. * This can be useful for testing. See the Robot extension sample for * an example of creating InputEvents to simulate user input. */ export class InputEvent { /** * The InputEvent class constructor produces an empty InputEvent. * It is uncommon to need to call this constructor -- normally only when trying to simulate input events. * But if you do, you must first set {@link diagram} to the Diagram before any other use. */ constructor(); /** * Make a copy of this InputEvent. * @virtual */ copy(): InputEvent; /** * Gets or sets the source diagram associated with the event. */ get diagram(): Diagram; set diagram(value: Diagram); /** * Gets or sets the point at which this input event occurred. * The Point is in view coordinates within the viewport, not in document coordinates. * This should be valid for mouse events. * For keyboard events, this is the last available mouse point. * @see {@link documentPoint} * @see {@link Diagram.transformViewToDoc} * @see {@link Diagram.transformDocToView} */ get viewPoint(): Point; set viewPoint(value: Point); /** * Gets or sets the point at which this input event occurred, in document coordinates. * The Point is in document coordinates, the same as the {@link GraphObject.position} * for {@link Part}s in the diagram. * This should be valid for mouse events. * For keyboard events, this is the last available mouse point. * @see {@link viewPoint} * @see {@link Diagram.transformViewToDoc} * @see {@link Diagram.transformDocToView} */ get documentPoint(): Point; set documentPoint(value: Point); /** * Gets or sets the modifier keys that were used with the mouse or keyboard event. * The number will be a combination of flags representing Control, Shift, Alt or Meta. * @see {@link control} * @see {@link shift} * @see {@link alt} * @see {@link meta} */ get modifiers(): number; set modifiers(value: number); /** * Gets or sets the numerical value representing the mouse button that caused this event. * * Only one mouse button can cause an event at a time, * but the set of all buttons currently pressed is kept in {@link buttons}. * * This property describes nothing during a `mousemove` event, * since no button press causes the event. Instead, use the convenience properties * {@link left}, {@link middle}, or {@link right}, or use the value * of {@link buttons} to determine which mouse buttons are * held during `mousemove` events. * * Common values for this property: * - 0: left mouse button * - 1: middle mouse button * - 2: right mouse button * * Other values are possible if the mouse has additional buttons. * * If there is no associated {@link event}, setting this also * sets the {@link buttons} flags to only this button. * * This property is valid if this is a mouse event. * @see {@link buttons} * @see {@link left} * @see {@link middle} * @see {@link right} */ get button(): number; set button(value: number); /** * Gets or sets the set of buttons that are currently being held down. * If this is a `mouseup` event, this set of buttons does not include * the button that was just released, which will be the value of {@link button}. * * Common values for this property: * - 0: not holding down any button * - 1: left mouse button * - 2: right mouse button * - 3: both left and right mouse buttons * - 4: middle mouse button * - 5: middle and left mouse buttons * - 6: middle and right mouse buttons * - 7: all three common mouse buttons * * Other values are possible if the mouse has additional buttons. * * This property is valid if this is a mouse event. * @see {@link button} * @see {@link left} * @see {@link middle} * @see {@link right} */ get buttons(): number; set buttons(value: number); /** * Gets or sets the key pressed or released as this event. * This property is valid if this is a keyboard event. * This corresponds to a `KeyboardEvent.key` * @see {@link commandKey} */ get key(): string; set key(value: string); /** * Gets or sets the code pressed or released as this event. * This property is valid if this is a keyboard event. * This corresponds to a `KeyboardEvent.code` * @see {@link commandKey} * @since 3.0 */ get code(): string; set code(value: string); /** * Gets or sets whether the InputEvent represents a mouse-down or a key-down event. * The default value is false. */ get down(): boolean; set down(value: boolean); /** * Gets or sets whether the InputEvent represents a mouse-up or a key-up event. * The default value is false. */ get up(): boolean; set up(value: boolean); /** * Gets or sets whether this event represents a click or a double-click. * It is zero if not a click; one if a single-click; two if a double-click. * This property is valid if this is a mouse event. */ get clickCount(): number; set clickCount(value: number); /** * Gets or sets the amount of change associated with a mouse-wheel rotation. * It is an abstract number, either positive or negative. * This property is valid if this is a mouse-wheel event. */ get delta(): number; set delta(value: number); /** * This property is true when the InputEvent is caused by a touch event that registered more than one touch. * @see {@link isTouchEvent} */ get isMultiTouch(): boolean; set isMultiTouch(value: boolean); /** * Gets or sets whether an InputEvent that applies to a {@link GraphObject} and bubbles * up the chain of containing {@link Panel}s is stopped from continuing up the chain. * * Some event handlers may set this to true to avoid getting any behavior from the containing Panels. * The default value is false. */ get handled(): boolean; set handled(value: boolean); /** * Gets or sets whether the underlying {@link event} is prevented from bubbling up * the hierarchy of HTML elements outside of the Diagram and whether any default action is canceled. * Setting this is uncommon, but may be needed in some {@link CommandHandler} overrides in order to * pass along events, such as keystrokes, to parent elements of the Diagram. * * Some event handlers may set this to true if the event should continue beyond the diagram's DIV * and result in any default behaviors by the user-agent. * The default value is false. * @since 2.2 * @see {@link handled} */ get bubbles(): boolean; set bubbles(value: boolean); /** * Gets or sets the platform's user-agent-supplied event for this event. * It may be null if no underlying event exists. * @see {@link timestamp} */ get event(): Event | null; set event(value: Event | null); /** * This read-only property is true when the InputEvent is caused by a touch event. * @see {@link isMultiTouch} */ get isTouchEvent(): boolean; /** * Gets or sets the time at which the event occurred, in milliseconds. */ get timestamp(): number; set timestamp(value: number); /** * Gets or sets the diagram associated with the canvas that the event is currently targeting. */ get targetDiagram(): Diagram | null; set targetDiagram(value: Diagram | null); /** * Gets or sets the {@link GraphObject} that is at the current mouse point, if any. * * For those events that are bubbled up the chain of parent {@link Panel}s, * this property provides access to the original {@link GraphObject} where the input event occurred. * @see {@link handled} */ get targetObject(): GraphObject | null; set targetObject(value: GraphObject | null); /** * Gets or sets whether the control key is being held down. * This is true if the key was pressed at the time of the event. * @see {@link modifiers} * @see {@link shift} * @see {@link alt} * @see {@link meta} */ get control(): boolean; set control(value: boolean); /** * Gets or sets whether the shift key is being held down. * This is true if the key was pressed at the time of the event. * @see {@link modifiers} * @see {@link control} * @see {@link alt} * @see {@link meta} */ get shift(): boolean; set shift(value: boolean); /** * Gets or sets whether the alt key is being held down. * This is true if the key was pressed at the time of the event. * @see {@link modifiers} * @see {@link control} * @see {@link shift} * @see {@link meta} */ get alt(): boolean; set alt(value: boolean); /** * Gets or sets whether the meta key is being held down. * This is true if the key was pressed at the time of the event. * @see {@link modifiers} * @see {@link control} * @see {@link shift} * @see {@link alt} */ get meta(): boolean; set meta(value: boolean); /** * Gets or sets whether the logical left mouse button is being held down. * This is true if the button was pressed at the time of the event. * * If this InputEvent has a {@link event} of type `MouseEvent` with `e.type` of "mouseup" or "mousedown", * this property uses the value of {@link button}. Otherwise, it uses the value of {@link buttons}. * * When setting, this sets the value of {@link buttons}. * Because a button must be pressed on an InputEvent, setting this to false does not modify the value * of {@link button}, but setting it to true does set {@link button}. * @see {@link button} * @see {@link middle} * @see {@link right} */ get left(): boolean; set left(value: boolean); /** * Gets or sets whether the logical right mouse button is being held down. * This is true if the button was pressed at the time of the event. * * If this InputEvent has a {@link event} of type `MouseEvent` with `e.type` of "mouseup" or "mousedown", * this property uses the value of {@link button}. Otherwise, it uses the value of {@link buttons}. * * When setting, this sets the value of {@link buttons}. * Because a button must be pressed on an InputEvent, setting this to false does not modify the value * of {@link button}, but setting it to true does set {@link button}. * @see {@link button} * @see {@link left} * @see {@link middle} */ get right(): boolean; set right(value: boolean); /** * Gets or sets whether the logical middle mouse button is being held down. * This is true if the button was pressed at the time of the event. * * If this InputEvent has a {@link event} of type `MouseEvent` with `e.type` of "mouseup" or "mousedown", * this property uses the value of {@link button}. Otherwise, it uses the value of {@link buttons}. * * When setting, this sets the value of {@link buttons}. * Because a button must be pressed on an InputEvent, setting this to false does not modify the value * of {@link button}, but setting it to true does set {@link button}. * @see {@link button} * @see {@link left} * @see {@link right} */ get middle(): boolean; set middle(value: boolean); /** * Given this InputEvent's {@link key} and {@link code}, this gets the lowercase key, * or else the code string, relevant for built-in Commands. * This is intended to normalize values across keyboard layouts in different languages. * * This will return one of the lowercase letters used by the {@link CommandHandler}: `'c', 'x', 'v', 'y', 'z', 'a', 'g'`, * or else a `KeyboardEvent.code` string for a key such as `'Delete', 'Insert', 'Backspace', 'ArrowDown'`, etc. * @since 3.0 */ get commandKey(): string; } /** * A DiagramEvent represents a more abstract event than an {@link InputEvent}. * They are raised on the {@link Diagram} class. * One can receive such events by registering a DiagramEvent listener on a Diagram * by calling {@link Diagram.addDiagramListener}. * The listener function, when called, will be passed an instance of a {@link DiagramEvent}. * Use the {@link name} property to decide what kind of diagram event it is. * The {@link diagram} property refers to the Diagram, and you can get additional information * from that, such as the {@link Diagram.lastInput}, which in turn provides information * such as {@link InputEvent.documentPoint} that may be relevant for that kind of DiagramEvent. * * The {@link subject} and {@link parameter} properties optionally provide additional information * about the diagram event. The subject could be a collection of {@link Part}s or it could be * an individual object such as a {@link Link} or a {@link GraphObject} within a {@link Node}. * Everything depends on the kind of diagram event that it is. * * Some DiagramEvents such as "ObjectSingleClicked" or "BackgroundDoubleClicked" are normally * associated with {@link InputEvent}s. * Some DiagramEvents such as "SelectionMoved" or "PartRotated" are associated with the * results of {@link Tool}-handled gestures or {@link CommandHandler} actions. * Some DiagramEvents are not necessarily associated with any input events at all, * such as "ViewportBoundsChanged", which can happen due to programmatic * changes to the {@link Diagram.position} and {@link Diagram.scale} properties. * * DiagramEvents that occur during a transaction may be called before the state of the whole diagram has settled down. * This often means that such events occur before a layout, so nodes may not have their final positions, * links may not have their final routes, and the {@link Diagram.documentBounds} and {@link Diagram.viewportBounds} * may not yet have been updated. * Such events may make additional changes to the diagram, which may in turn result in additional side-effects. * * DiagramEvents that occur outside of a transaction require you to start and commit a transaction around any side-effects that you want to do. * However, some DiagramEvents do not allow you to make any changes to the Diagram or Model. * * Currently defined diagram event names include: * - **"InitialAnimationStarting"**, the initial {@link AnimationManager.defaultAnimation} is about to start;
* this can be useful for customizing the initial animation, see {@link AnimationManager.initialAnimationStyle}. * - **"AnimationStarting"**, a {@link AnimationManager.defaultAnimation} is about to start;
* do not modify the Diagram or its Model in the event listener. * - **"AnimationFinished"**, a {@link AnimationManager.defaultAnimation} just completed;
* do not modify the Diagram or its Model in the event listener. * - **"BackgroundSingleClicked"**, a click that was not on any Part;
* if you make any changes, start and commit your own transaction. * - **"BackgroundDoubleClicked"**, a double-click that was not on any Part;
* if you make any changes, start and commit your own transaction. * - **"BackgroundContextClicked"**, a context-click that was not on any Part;
* if you make any changes, start and commit your own transaction. * - **"ChangingSelection"**, an operation is about to change the {@link Diagram.selection} collection,
* which is also the value of the {@link DiagramEvent.subject};
* do not make any changes to the selection or the diagram in the event listener; * note that just setting {@link Part.isSelected} will not raise this event, but tools and commands will. * - **"ChangedSelection"**, an operation has just changed the {@link Diagram.selection} collection,
* which is also the value of the {@link DiagramEvent.subject};
* do not make any changes to the selection or the diagram in the event listener; * note that just setting {@link Part.isSelected} will not raise this event, but tools and commands will. * - **"ClipboardChanged"**, Parts have been copied to the clipboard by {@link CommandHandler.copySelection};
* the {@link DiagramEvent.subject} is the collection of {@link Part}s;
* if you make any changes, start and commit your own transaction. * - **"ClipboardPasted"**, Parts have been copied from the clipboard into the Diagram by {@link CommandHandler.pasteSelection};
* the {@link DiagramEvent.subject} is the {@link Diagram.selection},
* and this is called within a transaction. * - **"DocumentBoundsChanged"**, the area of the diagram's Parts, {@link Diagram.documentBounds}, has changed;
* the {@link DiagramEvent.parameter} is the old {@link Rect} * - **"ExternalObjectsDropped"**, Parts have been copied into the Diagram by drag-and-drop from outside of the Diagram;
* the {@link DiagramEvent.subject} is the set of {@link Part}s that were dropped (which is also the {@link Diagram.selection}), * the {@link DiagramEvent.parameter} is the source {@link Diagram}, * and this is called within a transaction. If you choose, you can cancel the drop by executing: * e.diagram.toolManager.draggingTool.transactionResult = null; * - **"GainedFocus"**, the diagram has gained keyboard focus, such as after a call to {@link Diagram.focus}. * - **"InitialLayoutCompleted"**, the whole diagram layout has updated for the first time since a major change to the Diagram, such as replacing the Model;
* if you make any changes, you do not need to perform a transaction. * - **"LayoutCompleted"**, the whole diagram layout has just been updated;
* if you make any changes, you do not need to perform a transaction. * - **"LinkDrawn"**, the user has just created a new Link using {@link LinkingTool};
* the {@link DiagramEvent.subject} is the new {@link Link},
* and this is called within a transaction. * - **"LinkRelinked"**, the user has just reconnected an existing Link using {@link RelinkingTool} or {@link DraggingTool};
* the {@link DiagramEvent.subject} is the modified {@link Link},
* the {@link DiagramEvent.parameter} is the {@link GraphObject} port that the link was disconnected from,
* and this is called within a transaction. * - **"LinkReshaped"**, the user has just rerouted an existing Link using {@link LinkReshapingTool};
* the {@link DiagramEvent.subject} is the modified {@link Link},
* the {@link DiagramEvent.parameter} is the List of Points of the link's original route, * and this is called within a transaction. * - **"LostFocus"**, the diagram has lost keyboard focus, a.k.a. "blur". * - **"Modified"**, the {@link Diagram.isModified} property has been set to a new value -- * useful for marking a window as having been modified since the last save;
* do not modify the Diagram or its Model in the event listener. * - **"ObjectSingleClicked"**, a click that occurred on a GraphObject;
* the {@link DiagramEvent.subject} is the {@link GraphObject};
* if you make any changes, start and commit your own transaction. * - **"ObjectDoubleClicked"**, a double-click that occurred on a GraphObject;
* the {@link DiagramEvent.subject} is the {@link GraphObject};
* if you make any changes, start and commit your own transaction. * - **"ObjectContextClicked"**, a context-click that occurred on a GraphObject;
* the {@link DiagramEvent.subject} is the {@link GraphObject};
* if you make any changes, start and commit your own transaction. * - **"PartCreated"**, the user inserted a new Part by {@link ClickCreatingTool};
* the {@link DiagramEvent.subject} is the new {@link Part},
* and this is called within a transaction. * - **"PartResized"**, the user has changed the size of a GraphObject by {@link ResizingTool};
* the {@link DiagramEvent.subject} is the {@link GraphObject},
* the {@link DiagramEvent.parameter} is the original Size,
* and this is called within a transaction. * - **"PartRotated"**, the user has changed the angle of a GraphObject by {@link RotatingTool};
* the {@link DiagramEvent.subject} is the {@link GraphObject},
* the {@link DiagramEvent.parameter} is the original angle in degrees,
* and this is called within a transaction. * - **"SelectionMoved"**, the user has moved selected Parts by {@link DraggingTool};
* the {@link DiagramEvent.subject} is a Set of the moved Parts,
* and this is called within a transaction. * - **"SelectionCopied"**, the user has copied selected Parts by {@link DraggingTool};
* the {@link DiagramEvent.subject} is Set of the newly copied Parts,
* and this is called within a transaction. * - **"SelectionDeleted"**, the user has deleted selected Parts by {@link CommandHandler.deleteSelection};
* the {@link DiagramEvent.subject} is the collection of {@link Part}s that were deleted,
* and this is called within a transaction. * - **"SelectionDeleting"**, the user is about to delete selected Parts by {@link CommandHandler.deleteSelection};
* the {@link DiagramEvent.subject} is the {@link Diagram.selection} collection of Parts to be deleted,
* and this is called within a transaction. * - **"SelectionGrouped"**, the user has made a new Group out of the selected Parts by {@link CommandHandler.groupSelection};
* the {@link DiagramEvent.subject} is the new {@link Group},
* and this is called within a transaction. * - **"SelectionUngrouped"**, the user has removed a selected Group but kept its members by {@link CommandHandler.ungroupSelection};
* the {@link DiagramEvent.subject} is the collection of {@link Group}s that were ungrouped,
* the {@link DiagramEvent.parameter} is the collection of former member {@link Part}s that were ungrouped,
* and this is called within a transaction. * - **"SubGraphCollapsed"**, the user has collapsed selected Groups by {@link CommandHandler.collapseSubGraph};
* the {@link DiagramEvent.subject} is the collection of {@link Group}s that were collapsed,
* and this is called within a transaction. * - **"SubGraphExpanded"**, the user has expanded selected Groups by {@link CommandHandler.expandSubGraph};
* the {@link DiagramEvent.subject} is the collection of {@link Group}s that were expanded,
* and this is called within a transaction. * - **"TextEdited"**, the user has changed the string value of a TextBlock by {@link TextEditingTool};
* the {@link DiagramEvent.subject} is the edited {@link TextBlock},
* the {@link DiagramEvent.parameter} is the original string,
* and this is called within a transaction. * - **"ThemeChanged"**, the diagram's theme has changed, maybe as a result of setting {@link ThemeManager.currentTheme} * or calling {@link ThemeManager.set}. * - **"TreeCollapsed"**, the user has collapsed selected Nodes with subtrees by {@link CommandHandler.collapseTree};
* the {@link DiagramEvent.subject} is the collection of {@link Node}s that were collapsed,
* and this is called within a transaction. * - **"TreeExpanded"**, the user has expanded selected Nodes with subtrees by {@link CommandHandler.expandTree};
* the {@link DiagramEvent.subject} is the collection of {@link Node}s that were expanded,
* and this is called within a transaction. * - **"ViewportBoundsChanged"**, the visible area of the Diagram, {@link Diagram.viewportBounds}, has changed;
* the {@link DiagramEvent.subject} is an object whose "scale" property is the old {@link Diagram.scale} value, * whose "position" property is the old {@link Diagram.position} value, * whose "bounds" property is the old {@link Diagram.viewportBounds} value, * whose "canvasSize" property is the old size of the {@link Diagram.div}, and * whose "newCanvasSize" property is the new size of the {@link Diagram.div}, * the {@link DiagramEvent.parameter} is also the old viewportBounds {@link Rect}. */ export class DiagramEvent { /** * The DiagramEvent class constructor produces an empty DiagramEvent. * You should never need to call this constructor. * But if you do, you must first set {@link diagram} to the Diagram before any other use. */ constructor(); /** * Gets or sets the diagram associated with the event. */ get diagram(): Diagram; set diagram(value: Diagram); /** * Gets or sets the name of the kind of diagram event that this represents. * This property should always be set to one of the recognized list of names, * as listed in the documentation for {@link DiagramEvent}. */ get name(): string; set name(value: string); /** * Gets or sets an optional object that is the subject of the diagram event. * This property defaults to null. */ get subject(): any; set subject(value: any); /** * Gets or sets an optional object that describes the change to the subject of the diagram event. * This property defaults to null. */ get parameter(): any; set parameter(value: any); } /** * The signature for a function acting as a handler for {@link DiagramEvent}s. */ export type DiagramEventHandler = (e: DiagramEvent) => void; /** * A listing of all supported {@link DiagramEvent} names. * * `'InitialAnimationStarting' | * 'AnimationStarting' | * 'AnimationFinished' | * 'BackgroundSingleClicked' | * 'BackgroundDoubleClicked' | * 'BackgroundContextClicked' | * 'ChangingSelection' | * 'ChangedSelection' | * 'ClipboardChanged' | * 'ClipboardPasted' | * 'DocumentBoundsChanged' | * 'ExternalObjectsDropped' | * 'GainedFocus' | * 'InitialLayoutCompleted' | * 'LayoutCompleted' | * 'LinkDrawn' | * 'LinkRelinked' | * 'LinkReshaped' | * 'LostFocus' | * 'Modified' | * 'ObjectSingleClicked' | * 'ObjectDoubleClicked' | * 'ObjectContextClicked' | * 'PartCreated' | * 'PartResized' | * 'PartRotated' | * 'SelectionMoved' | * 'SelectionCopied' | * 'SelectionDeleted' | * 'SelectionDeleting' | * 'SelectionGrouped' | * 'SelectionUngrouped' | * 'SubGraphCollapsed' | * 'SubGraphExpanded' | * 'TextEdited' | * 'ThemeChanged' | * 'TreeCollapsed' | * 'TreeExpanded' | * 'ViewportBoundsChanged'` */ export type DiagramEventName = 'InitialAnimationStarting' | 'AnimationStarting' | 'AnimationFinished' | 'BackgroundSingleClicked' | 'BackgroundDoubleClicked' | 'BackgroundContextClicked' | 'ChangingSelection' | 'ChangedSelection' | 'ClipboardChanged' | 'ClipboardPasted' | 'DocumentBoundsChanged' | 'ExternalObjectsDropped' | 'GainedFocus' | 'InitialLayoutCompleted' | 'LayoutCompleted' | 'LinkDrawn' | 'LinkRelinked' | 'LinkReshaped' | 'LostFocus' | 'Modified' | 'ObjectSingleClicked' | 'ObjectDoubleClicked' | 'ObjectContextClicked' | 'PartCreated' | 'PartResized' | 'PartRotated' | 'SelectionMoved' | 'SelectionCopied' | 'SelectionDeleted' | 'SelectionDeleting' | 'SelectionGrouped' | 'SelectionUngrouped' | 'SubGraphCollapsed' | 'SubGraphExpanded' | 'TextEdited' | 'ThemeChanged' | 'TreeCollapsed' | 'TreeExpanded' | 'ViewportBoundsChanged' | 'InvalidateDraw'; /** * A TypeScript type for helping to declare GraphObject.make. */ export interface DiagramEventsInterface { AnimationStarting?: DiagramEventHandler; AnimationFinished?: DiagramEventHandler; BackgroundSingleClicked?: DiagramEventHandler; BackgroundDoubleClicked?: DiagramEventHandler; BackgroundContextClicked?: DiagramEventHandler; ChangingSelection?: DiagramEventHandler; ChangedSelection?: DiagramEventHandler; ClipboardChanged?: DiagramEventHandler; ClipboardPasted?: DiagramEventHandler; DocumentBoundsChanged?: DiagramEventHandler; ExternalObjectsDropped?: DiagramEventHandler; GainedFocus?: DiagramEventHandler; InitialLayoutCompleted?: DiagramEventHandler; LayoutCompleted?: DiagramEventHandler; LinkDrawn?: DiagramEventHandler; LinkRelinked?: DiagramEventHandler; LinkReshaped?: DiagramEventHandler; LostFocus?: DiagramEventHandler; Modified?: DiagramEventHandler; ObjectSingleClicked?: DiagramEventHandler; ObjectDoubleClicked?: DiagramEventHandler; ObjectContextClicked?: DiagramEventHandler; PartCreated?: DiagramEventHandler; PartResized?: DiagramEventHandler; PartRotated?: DiagramEventHandler; SelectionMoved?: DiagramEventHandler; SelectionCopied?: DiagramEventHandler; SelectionDeleted?: DiagramEventHandler; SelectionDeleting?: DiagramEventHandler; SelectionGrouped?: DiagramEventHandler; SelectionUngrouped?: DiagramEventHandler; SubGraphCollapsed?: DiagramEventHandler; SubGraphExpanded?: DiagramEventHandler; TextEdited?: DiagramEventHandler; ThemeChanged?: DiagramEventHandler; TreeCollapsed?: DiagramEventHandler; TreeExpanded?: DiagramEventHandler; ViewportBoundsChanged?: DiagramEventHandler; } /** * This enumeration specifies possible values for {@link ChangedEvent.change}. * @since 3.0 * @category Model */ export declare enum ChangeType { /** * For informational events, such as transactions and undo/redo operations. * The {@link ChangedEvent.object} refers to the {@link Transaction} affected, if any. * The {@link ChangedEvent.propertyName} distinguishes the different transaction or undo or redo stages. * The {@link ChangedEvent.oldValue} may provide the transaction name, if available, as given to {@link UndoManager.commitTransaction}. */ Transaction = 1, /** * For simple property changes. * The name of the property is given by {@link ChangedEvent.propertyName}. * The modified object is given by {@link ChangedEvent.object}. * Use the {@link ChangedEvent.oldValue} and {@link ChangedEvent.newValue} properties for the previous and next property values. * * For model changes, the {@link ChangedEvent.modelChange} may be non-empty, indicating a structural change to the model. */ Property = 2, /** * For inserting into collections. * The modified object is given by {@link ChangedEvent.object}. * Use the optional {@link ChangedEvent.propertyName} to distinguish between different collections on the object. * Use the {@link ChangedEvent.newValue} property to indicate the value that was inserted. * Use the optional {@link ChangedEvent.newParam} property to indicate where or how, such as an array index or dictionary key. */ Insert = 3, /** * For removing from collections. * The modified object is given by {@link ChangedEvent.object}. * Use the optional {@link ChangedEvent.propertyName} to distinguish between different collections on the object. * Use the {@link ChangedEvent.oldValue} property to indicate the value that was removed. * Use the optional {@link ChangedEvent.oldParam} property to indicate where or how, such as an array index or dictionary key. */ Remove = 4 } /** * A ChangedEvent represents a change to an object, typically a {@link GraphObject}, * but also for model data, a {@link Model}, or a {@link Diagram}. * The most common case is for remembering the name of a property * and the before-and-after values for that property. * * You can listen for changed events on the model using {@link Model.addChangedListener} * or {@link Diagram.addModelChangedListener}, and on the Diagram using {@link Diagram.addChangedListener}. * * There are four kinds of changes, represented by enumerated values: * {@link ChangeType.Property} (the most common), {@link ChangeType.Insert} and {@link ChangeType.Remove} * (to represent inserting or removing objects from collections), * and {@link ChangeType.Transaction} (to notify about beginning or ending transactions or undo or redo). * * The most common kind of ChangedEvent is a Property change. * The name of the property is given by {@link propertyName}. * The modified object is given by {@link object}. * Use the {@link oldValue} and {@link newValue} properties for the before and after property values. * * For an Insert ChangedEvent, the modified collection (often an Array) is a property value on the {@link object}. * The {@link propertyName} helps distinguish between different collections on the object. * Use the {@link newValue} property to indicate the value that was inserted. * Use the {@link newParam} property to indicate where or how, such as an array index or dictionary key. * * For a Remove ChangedEvent, the modified collection is a property value on the {@link object}. * The {@link propertyName} helps distinguish between different collections on the object. * Use the {@link oldValue} property to indicate the value that was removed. * Use the {@link oldParam} property to indicate where or how, such as an array index or dictionary key. * * Transaction ChangedEvents are generated by the {@link UndoManager}. * The {@link propertyName} names the nature of the ChangedEvent. * For the very first transaction, the property name is "StartingFirstTransaction". * This ChangedEvent precedes a ChangedEvent whose property name is "StartedTransaction", * which occurs for every top-level transaction. * * When ending a transaction, there is first a ChangedEvent whose name is "ComittingTransaction". * This is followed by one with either "CommittedTransaction" or "RolledBackTransaction", * depending on how the transaction is ending. * The {@link oldValue} provides the transaction name and the {@link object} is the {@link Transaction} being finished. * (Note that the Transaction value may be null if no Transaction is available at that time, * perhaps because there were no changes made during the transaction.) * That Transaction can be scanned to look for ChangedEvents that you may wish to record in a database, * all within a single database transaction. * * There are also Transaction ChangedEvents corresponding to "StartingUndo", "FinishedUndo", * "StartingRedo", and "FinishedRedo". * The {@link object} property provides the {@link Transaction} that is about-to-be or just-was undone or redone. * * Non-Transaction ChangedEvents are remembered by the {@link UndoManager}, if {@link UndoManager.isEnabled}, * and held in the {@link UndoManager.history} as {@link Transaction}s which hold lists of ChangedEvents. * That is why ChangedEvent implements {@link undo} and {@link redo} of the change that it remembers. * * When the ChangedEvent represents a change to a {@link Model}, the value of {@link model} is non-null * and the value of {@link diagram} is meaningless. * If the change is a structural change to the model, * the value of {@link modelChange} indicates the kind of change. * Currently defined model changed event names include: * - **"nodeDataArray"**, after the model's {@link Model.nodeDataArray} is replaced, inserted into or removed from * (setting {@link Model.nodeDataArray} or calling {@link Model.addNodeData} or {@link Model.removeNodeData}) * - **"nodeKey"**, after changing a node data's unique key ({@link Model.setKeyForNodeData}) * - **"nodeCategory"**, after changing a node data's category ({@link Model.setCategoryForNodeData}) * - **"linkDataArray"**, after the model's {@link GraphLinksModel.linkDataArray} is replaced, inserted into or removed from * (setting {@link GraphLinksModel.linkDataArray} or calling {@link GraphLinksModel.addLinkData} * or {@link GraphLinksModel.removeLinkData}) * - **"linkKey"**, after changing a link data's unique key ({@link GraphLinksModel.setKeyForLinkData}) * - **"linkCategory"**, after changing a link data's category ({@link GraphLinksModel.setCategoryForLinkData}) * - **"linkFromKey"**, after changing a link data's "from" node key ({@link GraphLinksModel.setFromKeyForLinkData}) * - **"linkToKey"**, after changing a link data's "to" node key ({@link GraphLinksModel.setToKeyForLinkData}) * - **"linkFromPortId"**, after changing a link data's "from" port identifier string ({@link GraphLinksModel.setFromPortIdForLinkData}) * - **"linkToPortId"**, after changing a link data's "to" port identifier string ({@link GraphLinksModel.setToPortIdForLinkData}) * - **"linkLabelKeys"**, after replacing, inserting into, or removing from a link data's array of keys to label nodes * (calling {@link GraphLinksModel.setLabelKeysForLinkData}, {@link GraphLinksModel.addLabelKeyForLinkData}, * or {@link GraphLinksModel.removeLabelKeyForLinkData}) * - **"nodeGroupKey"**, after changing a node data's key for a containing group data ({@link GraphLinksModel.setGroupKeyForNodeData}) * - **"nodeParentKey"**, after changing a node data's "parent" node key ({@link TreeModel.setParentKeyForNodeData}) * - **"parentLinkCategory"**, after changing a node data's "parent" link's category({@link TreeModel.setParentLinkCategoryForNodeData}) * - other names are for internal implementation use only, only on Transaction ChangedEvents * * The value of {@link ChangedEvent.propertyName} indicates the actual name of the property that was modified. * {@link ChangedEvent.modelChange} is a non-empty string only when there is a known structural change to the model, * not just the setting of some property on some object. * * When the ChangedEvent represents a change to a {@link Diagram} or a {@link GraphObject} within a diagram, * the value of {@link diagram} is non-null and * the values of {@link model} and {@link modelChange} are meaningless. * * Please note that ChangedEvents can be raised for many different causes. * You may not be interested in changes to temporary objects -- in that case ignore the ChangedEvent when * {@link Model.skipsUndoManager} or {@link Diagram.skipsUndoManager} is true. * @category Model */ export class ChangedEvent { /** * The ChangedEvent class constructor produces an empty ChangedEvent object. * It would be unusual to need to call this constructor. * Normally the Diagram automatically constructs ChangedEvents as the diagram or its GraphObjects are modified, * and the Model automatically constructs ChangedEvents as the model or its data are modified. */ constructor(); /** * @deprecated See {@link ChangeType.Transaction}. */ static readonly Transaction = ChangeType.Transaction; /** * @deprecated See {@link ChangeType.Property}. */ static readonly Property = ChangeType.Property; /** * @deprecated See {@link ChangeType.Insert}. */ static readonly Insert = ChangeType.Insert; /** * @deprecated See {@link ChangeType.Remove}. */ static readonly Remove = ChangeType.Remove; /** * Forget any object references that this ChangedEvent may have. */ clear(): void; /** * Make a copy of this ChangedEvent. * ChangedEvents are copied when the {@link UndoManager} adds to a {@link Transaction}. */ copy(): ChangedEvent; /** * This is a convenient method to get the right value, depending on the value of undo, * when implementing a state change as part of an undo or a redo. * @param undo - If true, returns the oldValue, otherwise returns the newValue. * @returns Either the oldValue or the newValue. */ getValue(undo: boolean): any; /** * This is a convenient method to get the right parameter value, depending on the value of undo, * when implementing a state change as part of an undo or a redo. * @param undo - If true, returns the oldParam, otherwise returns the newParam. * @returns Either the oldParam or the newParam. */ getParam(undo: boolean): any; /** * This predicate returns true if you can call undo(). * @returns True if ready for undo() to be called. */ canUndo(): boolean; /** * Reverse the effects of this object change. * canUndo() must be true for this method to have any effect. */ undo(): void; /** * This predicate returns true if you can call redo(). * @returns True if ready for redo() to be called. */ canRedo(): boolean; /** * Re-perform this object change after an undo(). * canRedo() must be true for this method to have any effect. */ redo(): void; /** * Gets or sets the {@link Model} or {@link TreeModel} or {@link GraphLinksModel} that was modified. * When this property is non-null, the {@link diagram} property will be null. * However this property and the {@link diagram} property may both be null simultaneously, * when no particular model or diagram applies. */ get model(): Model | null; set model(value: Model | null); /** * Gets or sets the {@link Diagram} that was modified. * When this property is non-null, the {@link model} property will be null. * However this property and the {@link model} property may both be null simultaneously, * when no particular model or diagram applies. */ get diagram(): Diagram | null; set diagram(value: Diagram | null); /** * Gets or sets the nature of change that occurred. * The default is {@link ChangeType.Property}. * Other values are {@link ChangeType.Insert}, {@link ChangeType.Remove}, * and {@link ChangeType.Transaction}. */ get change(): ChangeType; set change(value: ChangeType); /** * Gets or sets the name of the model change, reflecting a change to * model data in addition to a change to the model itself. * * The default is an empty string, which indicates that this is just * a regular change to some object's state, probably its property. * For a list of possible model change names, see the documentation for {@link ChangedEvent}. * The names are compared in a case-sensitive manner. */ get modelChange(): string; set modelChange(value: string); /** * Gets or sets the name of the property change. * The default is an empty string, which is not a valid property name. * This property can be useful even when the type of change is * not {@link ChangeType.Property}, because it can help identify * the collection in the {@link object} that was modified * (for {@link ChangeType.Insert} or {@link ChangeType.Remove}) * or the stage of the current transaction (for {@link ChangeType.Transaction}). */ get propertyName(): string | ((a: ObjectData, b: any) => any); set propertyName(value: string | ((a: ObjectData, b: any) => any)); /** * This read-only property is true when this ChangedEvent is of type {@link ChangeType.Transaction} and represents the end of a transactional change. * It is implemented as: * ```js * return (this.change === ChangeType.Transaction && * (this.propertyName === "CommittedTransaction" || * this.propertyName === "FinishedUndo" || * this.propertyName === "FinishedRedo")); * ``` */ get isTransactionFinished(): boolean; /** * Gets or sets the Object that was modified. * The default is null. * * For {@link ChangeType.Transaction} changes, this may be the {@link Transaction}. */ get object(): ObjectData | null; set object(value: ObjectData | null); /** * Gets or sets the previous or old value that the property had. * The default is null. */ get oldValue(): any; set oldValue(value: any); /** * Gets or sets an optional value associated with the old value. * Most properties do not require any parameter to describe the change. * This is typically a value that helps distinguish the old value, such as an index into an array. * It is null if it is not used. * The default is null. */ get oldParam(): any; set oldParam(value: any); /** * Gets or sets the next or current value that the property has. * The default is null. */ get newValue(): any; set newValue(value: any); /** * Gets or sets an optional value associated with the new value. * Most properties do not require any parameter to describe the change. * This is typically a value that helps distinguish the new value, such as an index into an array. * It is null if it is not used. * The default is null. */ get newParam(): any; set newParam(value: any); } /** * The signature for a function acting as a handler for {@link ChangedEvent}s. */ export type ChangedEventHandler = (e: ChangedEvent) => void; /** * A Transaction holds a list of {@link ChangedEvent}s collected during a transaction, * as the value of the read-only {@link changes} property. * * Start a transaction by calling {@link UndoManager.startTransaction} * (or {@link Model.startTransaction} or {@link Diagram.startTransaction}, which call that method). * Be sure to finish a transaction with a matching call to {@link UndoManager.commitTransaction} * (or {@link Model.commitTransaction} or {@link Diagram.commitTransaction}), * or a call to {@link UndoManager.rollbackTransaction} * (or the same named methods on {@link Model} or {@link Diagram}). * * If you are performing multiple or repeated changes to a model or diagram, * surround all of the code with calls to start and commit the transaction -- * do not perform repeated calls to start-commit-start-commit. * Typically each change caused by the user, such as a button click or a change of focus or a mouse drag, * should perform one transaction in which all changes are made. * All of the predefined commands and tools perform transactions. * * Undoing or redoing a transaction is done by calling {@link UndoManager.undo} or {@link UndoManager.redo}. * Those methods call the {@link undo} or {@link redo} methods here. * * The {@link UndoManager} holds a list of Transactions in its {@link UndoManager.history}. * @category Model */ export class Transaction { /** * Construct an object holding an empty list of {@link ChangedEvent}s * and no {@link name}. * It would be very unusual to call this -- normally transactions are constructed * automatically upon calls to {@link Model.commit}, {@link Diagram.commit}, * {@link Model.startTransaction}, or {@link Diagram.startTransaction}. */ constructor(); /** * Clear all of the saved changes. */ clear(): void; /** * This predicate returns true if you can call {@link undo}, * namely when {@link isComplete} is true. * @returns true if ready for {@link undo} to be called. */ canUndo(): boolean; /** * Undo all of the changes, in reverse order. * This is normally called only by the {@link UndoManager}. * {@link canUndo} must be true for this method to have any effect. */ undo(): void; /** * This predicate returns true if you can call {@link redo}, * namely when {@link isComplete} is true. * @returns true if ready for {@link redo} to be called. */ canRedo(): boolean; /** * Re-perform these changes after an {@link undo}. * This is normally called only by the {@link UndoManager}. * {@link canRedo} must be true for this method to have any effect. */ redo(): void; /** * Remove all but the first and last Property ChangedEvents for each property for each object. * * This is now called by {@link DraggingTool.stopTransaction} in order to reduce the memory saved by each dragging transaction. * @since 2.2 */ optimize(): void; /** * This read-only property returns the list of {@link ChangedEvent}s. * The changes are stored in order of occurrence. * * You should not modify this list. */ get changes(): List; /** * Gets or sets the transaction name for this collection of changes. * This is set by a top-level call to {@link UndoManager.commitTransaction}. */ get name(): string; set name(value: string); /** * Gets or sets whether we can add more {@link ChangedEvent}s to this list of changes. * This is initially false. * It is set to true by {@link UndoManager.commitTransaction} and {@link UndoManager.rollbackTransaction}. */ get isComplete(): boolean; set isComplete(value: boolean); } /** * An UndoManager observes and records model and diagram changes in transactions and * supports undo/redo operations. * You will need to set the {@link isEnabled} property to true in order for * the UndoManager to record changes and for users to perform an undo or a redo. * * Typically an operation will call {@link startTransaction}, * make some changes to the {@link Model} and/or {@link Diagram}, * and then call {@link commitTransaction}. * Any {@link ChangedEvent}s that occur will be recorded in a * {@link Transaction} object. * If for some reason you do not wish to complete the transaction * successfully, you can call {@link rollbackTransaction} instead * of {@link commitTransaction}. * * For convenience the {@link Diagram.commit} and {@link Model.commit} methods * execute a function within a transaction and then perform a commit, * or else a rollback upon an error. * * The {@link history} property is a list of {@link Transaction}s. * {@link commitTransaction} will add the {@link currentTransaction} * to the {@link history} list. * {@link rollbackTransaction} will undo the changes remembered in the * {@link currentTransaction} and then discard it, without changing the {@link history}. * You can limit how many transactions are remembered in the history * by setting {@link maxHistoryLength}. * * Transactions may be nested. * Be sure to call either {@link commitTransaction} or {@link rollbackTransaction} * for each call to {@link startTransaction}. * Avoid repeated start-commit-start-commit calls as a result of a user's actions. * Instead, start, make all changes, and then commit. * * If you want to restore the diagram to the state before the latest complete * transaction, call {@link undo}. * Call {@link redo} to change the diagram to a later state. * If after some number of undo's you start a transaction, * all of the history after the current state is discarded, * and a new transaction may be recorded. * You cannot undo or redo during a transaction. * * Initially each {@link Model} has its own UndoManager. * UndoManagers may be shared by multiple Models by replacing * the standard {@link Model.undoManager} created by the model constructor. * * There are several informational properties: * - {@link isInTransaction} is true when a top-level transaction has been started that has not yet been committed or rolled-back. * - {@link currentTransaction} holds the flattened list of all {@link ChangedEvent}s * that have happened within the current transaction. * - {@link transactionLevel} indicates the current depth of nesting. * - {@link nestedTransactionNames} holds the stack of transaction names supplied to * {@link startTransaction} calls. * - {@link history} holds only complete top-level transactions. * - {@link isUndoingRedoing} is true during a call to {@link undo} or {@link redo}. * - {@link historyIndex} indicates which {@link Transaction} in the {@link history} is the next to be "undone"; * this is decremented by each undo and incremented by each redo. * - {@link transactionToUndo} and {@link transactionToRedo} indicate which {@link Transaction} may be undone or redone next, if any. * - {@link models} returns an iterator over all of the {@link Model}s that this UndoManager is handling. * * A transaction may not be ongoing when replacing a {@link Diagram.model}, * because it would not make sense to be replacing the UndoManager (the {@link Model.undoManager}) * while changes are being recorded. * * Replacing a {@link Diagram.model} copies certain properties from the old UndoManager to the new one, * including {@link isEnabled} and {@link maxHistoryLength}. * @category Model */ export class UndoManager { /** * The constructor produces an empty UndoManager * with no transaction history. * It is unusual to call this -- an UndoManager is automatically constructed for a Model * by the Model constructor. */ constructor(init?: Partial); /** * Clear all of the {@link Transaction}s and clear all other state, * including any ongoing transaction without rolling back. * However, this maintains its references to its {@link Model}s. * * You should not call this method during a transaction. */ clear(): void; /** * (undocumented) * Copy persistent properties from an old UndoManager to this new one. * This is called by the {@link Diagram.model} property setter. * @virtual * @param old */ copyProperties(old: UndoManager): void; /** * Make sure this UndoManager knows about a {@link Model} for which * it may receive {@link ChangedEvent}s when the given {@link Model} is changed. * The model will also receive notifications about transactions and undo or redo operations. * * You should not call this method during a transaction. * @param model - A {@link Model} that this UndoManager is managing. * @see {@link models} * @see {@link removeModel} */ addModel(model: Model): void; /** * Inform this UndoManager that it will no longer be receiving {@link ChangedEvent}s * when the given {@link Model} is changed. * The model will no longer receive notifications about transactions and undo or redo operations. * * You should not call this method during a transaction. * If you call this method between transactions when there is a transaction history, * you should be careful that there are no {@link ChangedEvent}s referring to that model in any {@link Transaction}s. * @param model - A {@link Model} that this UndoManager should no longer manage. * @see {@link models} * @see {@link addModel} */ removeModel(model: Model): void; /** * Begin a transaction, where the changes are held by a {@link Transaction} object * as the value of {@link currentTransaction}. * You must call either {@link commitTransaction} or {@link rollbackTransaction} afterwards. * * For convenience, this method is called by {@link Model.startTransaction} and {@link Diagram.startTransaction}. * * Transactions can be nested. * Starting or ending a nested transaction will return false. * Nested transactions will share the same {@link Transaction} list of {@link ChangedEvent}s. * * Starting a transaction will not necessarily cause {@link currentTransaction} to be non-null. * A {@link Transaction} object is usually only created by {@link handleChanged} when a {@link ChangedEvent} first occurs. * @param tname - a short string describing the transaction, pushed onto the {@link nestedTransactionNames} stack. * @returns true if starting a top-level transaction. * @see {@link commitTransaction} * @see {@link rollbackTransaction} */ startTransaction(tname?: string): boolean; /** * Commit the current transaction started by a call to {@link startTransaction}. * * For convenience, this method is called by {@link Model.commitTransaction} and {@link Diagram.commitTransaction}. * * If this call stops a top-level transaction, * we mark the {@link currentTransaction} as complete ({@link Transaction.isComplete}), * we add the {@link Transaction} to the {@link history} list, * and we return true. * Committing a transaction when there have been some undos without corresponding * redos will throw away the {@link Transaction}s holding changes that happened * after the current state, before adding the new {@link Transaction} to the * {@link history} list. * @param tname - a short string describing the transaction; * this is recorded as the {@link Transaction.name} and need not be the same as the string passed to {@link startTransaction}. * If the value is an empty string or not supplied, this will use the name given to {@link startTransaction}. * @returns true if ending a top-level transaction. * @see {@link startTransaction} * @see {@link rollbackTransaction} */ commitTransaction(tname?: string): boolean; /** * Rollback the current transaction started by a call to {@link startTransaction}, undoing any changes. * * For convenience, this method is called by {@link Model.rollbackTransaction} and {@link Diagram.rollbackTransaction}. * * This undoes and then discards the changes in the {@link currentTransaction}. * You must have started a transaction previously. * @returns true if ending a top-level transaction. * @see {@link startTransaction} * @see {@link commitTransaction} */ rollbackTransaction(): boolean; /** * After an undo, call this to discard all of the transactions after * this point in the history, as indicated by the {@link historyIndex}. * This method is called when a transaction occurs after some number of undo's * without the same number of redo's, in order to remove all of the transactions * that happened after the current history point, and then adding the new transaction. * * This modifies the {@link history} but leaves {@link historyIndex} unchanged. * After a successful discard, {@link canRedo} will return false. * * This method does nothing if {@link canRedo} returns false, * or if an undo or a redo is ongoing. */ discardHistoryAfterIndex(): void; /** * This predicate returns true if you can call {@link undo}. * This will return false if {@link isEnabled} is false (as it is by default), * if any transaction is ongoing, or * if there is no {@link transactionToUndo} that can be undone. * @returns true if ready for {@link undo} to be called. */ canUndo(): boolean; /** * Reverse the effects of the {@link transactionToUndo}. * {@link canUndo} must be true for this method to have any effect. * * This is called by {@link CommandHandler.undo}. * * This will raise a "StartingUndo" {@link ChangedEvent} of type {@link ChangeType.Transaction}, * perform the {@link Transaction.undo} on the {@link transactionToUndo}, and then * raise a "FinishedUndo" {@link ChangedEvent} of type {@link ChangeType.Transaction}. * The two ChangedEvents are to let model listeners know that an undo is about to take place * and that it just finished. * {@link isUndoingRedoing} will temporarily be set to true during this operation. */ undo(): void; /** * This predicate returns true if you can call {@link redo}. * This will return false if {@link isEnabled} is false (as it is by default), * if any transaction is ongoing, or * if there is no {@link transactionToRedo} that can be redone. * @returns true if ready for {@link redo} to be called. */ canRedo(): boolean; /** * After an {@link undo}, re-perform the changes in {@link transactionToRedo}. * {@link canRedo} must be true for this method to have any effect. * * This is called by {@link CommandHandler.redo}. * * This will raise a "StartingRedo" {@link ChangedEvent} of type {@link ChangeType.Transaction}, * perform the {@link Transaction.redo} on the {@link transactionToRedo}, and then * raise a "FinishedRedo" {@link ChangedEvent} of type {@link ChangeType.Transaction}. * The two ChangedEvents are to let model listeners know that a redo is about to take place * and that it just finished. * {@link isUndoingRedoing} will temporarily be set to true during this operation. */ redo(): void; /** * Maybe record a {@link ChangedEvent} in the {@link currentTransaction}. * This calls {@link skipsEvent} to see if this should ignore the change. * If {@link skipsEvent} returns false, this creates a copy of the {@link ChangedEvent} * and adds it to the {@link currentTransaction}. * If there is no {@link currentTransaction}, this first creates and remembers it. * * This method always ignores all changes while performing * an {@link undo} or {@link redo}. * This method is also a no-op if {@link isEnabled} is false. * @param e - a {@link ChangedEvent}. */ handleChanged(e: ChangedEvent): void; /** * This predicate is called by {@link handleChanged} to decide if a {@link ChangedEvent} * is not interesting enough to be remembered. * * Transactional events (of change type {@link ChangeType.Transaction}) are always skipped. * Changed events for {@link GraphObject}s that are in {@link Layer.isTemporary} layers are also skipped. * * Sometimes changed events do not even get to {@link handleChanged} because * {@link Model.skipsUndoManager} or {@link Diagram.skipsUndoManager} is true. * @virtual * @param e - the {@link ChangedEvent} received by {@link handleChanged}. * @returns true to not record the change. */ skipsEvent(e: ChangedEvent): boolean; /** * This read-only property returns an iterator for all of the {@link Model}s that this UndoManager is handling. * @see {@link addModel} * @see {@link removeModel} */ get models(): Iterator; /** * Gets or sets whether this UndoManager records any changes. * The default value is false -- you need to set this to true if * you want the user to be able to undo or redo. * * You can temporarily turn off recording by setting {@link Diagram.skipsUndoManager} * and {@link Model.skipsUndoManager} to true. */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * This read-only property returns the {@link Transaction} in the {@link history} to be undone next. * The value may be null if the UndoManager is not ready to perform an undo. * @see {@link transactionToRedo} */ get transactionToUndo(): Transaction | null; /** * This read-only property returns the {@link Transaction} in the {@link history} to be redone next. * The value may be null if the UndoManager is not ready to perform a redo. * @see {@link transactionToUndo} */ get transactionToRedo(): Transaction | null; /** * This read-only property is true during a call to {@link undo} or {@link redo}. */ get isUndoingRedoing(): boolean; /** * This read-only property returns the whole history, a list of all of the {@link Transaction}s, * each representing a transaction with some number of {@link ChangedEvent}s. * * You should not modify this List. */ get history(): List; /** * Gets or sets the maximum number of transactions that this undo manager will remember. * When a transaction is committed and the number exceeds this value, * the UndoManager will discard the oldest transaction(s) in order to meet this limit. * The initial value is 999. * Any new value must be an integer. * A negative value is treated as if there were no limit. * A zero value will not remember any Transactions in the {@link history}, * but will allow commits and rollbacks to occur normally, * including raising "Transaction" type {@link ChangedEvent}s. * * This property is useful in helping limit the memory consumption of typical applications. * But this does not limit the number of {@link ChangedEvent}s that are recorded, * because there may be an unlimited number of those within each {@link Transaction}. * Decreasing this value will not necessarily remove any existing {@link Transaction}s * if there currently exist more in {@link history} than the new value permits. */ get maxHistoryLength(): number; set maxHistoryLength(value: number); /** * This read-only property returns the index into {@link history} for the current undoable {@link Transaction}. * The value is -1 if there is no undoable {@link Transaction} to be undone. */ get historyIndex(): number; /** * This read-only property returns the current {@link Transaction} for recording additional model change events. * This is initialized and augmented by {@link handleChanged} * before it is added to {@link history} by a top-level call * to {@link commitTransaction}. * The value will be null between transactions. */ get currentTransaction(): Transaction | null; /** * This read-only property returns the current transaction level. * The value is zero when there is no ongoing transaction. * The initial value is zero. * {@link startTransaction} will increment this value; * {@link commitTransaction} or {@link rollbackTransaction} will decrement it. * When this value is greater than zero, {@link canUndo} * and {@link canRedo} will be false, because * additional logically related model change events may occur. */ get transactionLevel(): number; /** * This read-only property is true after the first call to {@link startTransaction} * and before a corresponding call to {@link commitTransaction} or {@link rollbackTransaction}. * * During a transaction {@link canUndo} and {@link canRedo} will be false. * {@link currentTransaction} may be non-null if any {@link ChangedEvent}s were recorded. */ get isInTransaction(): boolean; /** * This read-only property returns a stack of ongoing transaction names. * The outermost transaction name will be the first item in the list. * The last one will be the name of the most recent (nested) call * to {@link startTransaction}. * * You should not modify this List. */ get nestedTransactionNames(): List; } /** * Tools handle mouse, keyboard, and touch events. * The currently running tool, {@link Diagram.currentTool}, receives all input events from the {@link Diagram} * via canonicalized {@link InputEvent}s. *

* For more discussion, see Introduction to Tools. * See samples that make use of tools in the samples index. * * Most tools are "mode-less" tools that are managed by the {@link ToolManager}, * which chooses the current tool based on the kind and position of the mouse event and the parts in the diagram. * The {@link ToolManager} has properties holding instances of most of the pre-defined {@link Tool} classes. * These classes include: * - In the {@link ToolManager.mouseDownTools} {@link List}: * - {@link ActionTool} * - {@link RelinkingTool} * - {@link LinkReshapingTool} * - {@link RotatingTool} * - {@link ResizingTool} * * - In the {@link ToolManager.mouseMoveTools} {@link List}: * - {@link LinkingTool} * - {@link DraggingTool} * - {@link DragSelectingTool} * - {@link PanningTool} * * - In the {@link ToolManager.mouseUpTools} {@link List}: * - {@link ContextMenuTool} * - {@link TextEditingTool} * - {@link ClickCreatingTool} * - {@link ClickSelectingTool} * * The ToolManager chooses a tool to run as the diagram's current tool by finding in its lists of tools the first tool * whose {@link canStart} method returns true. The ToolManager then sets {@link Diagram.currentTool} to be that tool. * * A tool is in the "running" state when it is the value of {@link Diagram.currentTool}. * The {@link Diagram.currentTool} property setter will call {@link doStop} on the old tool * and then call {@link doStart} on the new tool. * * A tool can then go into the "active" state once it decides it can actually do something. * This happens with a call to {@link doActivate}, normally called by the ToolManager. * Later it is deactivated ({@link doDeactivate}) and then stopped. * {@link isActive} should be true when the tool is "active". * Often tools should ignore certain common events, such as calls to {@link doMouseMove}, * unless the tool {@link isActive}. * * You can prevent a "mode-less" tool (i.e. one managed by the {@link ToolManager}) * from being started by the ToolManager by setting {@link isEnabled} to false. * * You can also go into a particular "mode" by setting {@link Diagram.currentTool} explicitly, * thereby circumventing the normal operation of the {@link ToolManager}. * This ignores the {@link isEnabled} property and does not call the {@link canStart} predicate. * The behavior will depend on the tool -- not all of the predefined tools support operating as a "modal" tool. * * Tools cannot be shared amongst multiple Diagrams. * * If you define a Tool subclass, you may override any of the methods whose names start with "do" * and any other methods that are documented to be overridable, such as {@link canStart}. * However you must seriously consider calling the base method in order to gets its default behavior. * There may be situations where not calling the base method may cause subtle bugs. * But that depends on the method and the tool. * Please read the Introduction page on Extensions for how to override methods and how to call the base method. * @category Tool */ export abstract class Tool { /** * Don't construct this directly -- this is an abstract class. */ constructor(); /** * This read-only property returns the {@link Diagram} that owns this tool and * for which this tool is handling input events. */ get diagram(): Diagram; set diagram(val: Diagram); /** * The diagram asks each tool to update any adornments the tool might * use for a given part. * If the tool uses its own tool handles, * this should display them or hide them as appropriate. * Typically this should only show them if the part is selected. * * By default this method does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param part */ updateAdornments(part: Part): void; /** * This predicate is used by the {@link ToolManager} to decide if this tool can be started mode-lessly * by mouse and touch events. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * By default this method returns {@link isEnabled}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns true if {@link isEnabled} is true and * if the {@link Diagram.toolManager} can make this tool the {@link Diagram.currentTool} and * then call the {@link doStart} method. */ canStart(): boolean; /** * The Diagram calls this method when this tool becomes the current tool; you should not call this method. * Tool implementations should perform their per-use initialization here, such * as setting up internal data structures, or capturing the mouse. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * You should not call this method -- only the {@link Diagram.currentTool} property setter should call this method. * * By default this method does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * If you override this method, it is commonplace to also override {@link doStop} to clean up whatever you set up in this method. * @virtual */ doStart(): void; /** * The Diagram calls this method after setting {@link Diagram.currentTool}, * to make the new tool active. * This should set {@link isActive} to true. * Overrides of this method might call {@link startTransaction}, * if this tool's activity involves modification of the model. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * You should call this method only after setting {@link Diagram.currentTool} to the Tool that you want to activate. * * By default this only sets {@link isActive} to true. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * If you override this method, it is commonplace to also override {@link doDeactivate} to clean up whatever you set up in this method. * @virtual */ doActivate(): void; /** * The Diagram calls this method on the old tool when * {@link Diagram.currentTool} is set to a new tool. * This needs to set {@link isActive} to false. * Overrides of this method might call {@link stopTransaction}, * if this tool's activity involves modification of the model. * * You should have no reason to call this method, because it is automatically called by the * {@link Diagram.currentTool} property setter on the old tool. * * By default this only sets {@link isActive} to false. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * It is commonplace to override this method in order to clean up whatever you have set up in an override of {@link doActivate}. * @virtual */ doDeactivate(): void; /** * The Diagram calls this method when this tool stops being the current tool; you should not call this method. * Tool implementations should perform their per-use cleanup here, * such as releasing mouse capture. * * You should not call this method -- only the {@link Diagram.currentTool} property setter should call this method. * If you want to stop a tool unexpectedly, you should call {@link doCancel}. * If your implementation of a tool wants to stop itself, you should call {@link stopTool}. * * By default this method does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * It is commonplace to override this method in order to clean up whatever you have set up in an override of {@link doStart}. * @virtual */ doStop(): void; /** * The diagram will call this method when the user wishes to cancel the * current tool's operation. * Typically this is called when the user hits the ESCAPE key. * This should restore the original state of what was modified by this tool, and then it should call {@link stopTool}. * This method is not responsible for cleaning up any side-effects that should be performed * by {@link doDeactivate} and/or {@link doStop}, which will always be called whether the tool stops normally or abnormally. * * By default this method just sets {@link transactionResult} to null and calls {@link stopTool}. * You will want to override this method even in tools that call {@link startTransaction} and {@link stopTransaction}, * because the {@link UndoManager} might not be enabled. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doCancel(): void; /** * If the {@link Diagram.currentTool} is this tool, * stop this tool and start the {@link Diagram.defaultTool} * by making it be the new current tool. * The implementation of various tool methods can call this method to stop the current tool. * This will call {@link doStop} -- you should not call that method directly. * * If you want to stop the current tool and have it restore the original state, call {@link doCancel}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ stopTool(): void; /** * The diagram will call this method upon a mouse down event. * This is normally overridden for mouse-down tools; * it is not called for mouse-move or mouse-up tools. * However it may also be called when the tool is run in a modal fashion, * when code explicitly sets the diagram's {@link Diagram.currentTool}. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * By default this method checks {@link isActive}; if that is false it calls {@link canStart}. * If that in turn is true, this calls {@link doActivate}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseDown(): void; /** * The diagram will call this method upon a mouse move event. * This is normally overridden for mouse-move tools; * it is not called for mouse-up tools. * However it may also be called when the tool is run in a modal fashion, * when code explicitly sets the diagram's {@link Diagram.currentTool}. * An override of this method usually does nothing when {@link isActive} is false. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * By default this method does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseMove(): void; /** * The diagram will call this method upon a mouse up event. * This is normally overridden for mouse-up tools. * An override of this method usually does nothing when {@link isActive} is false, * except for calling {@link stopTool}. * Tools normally stop upon a mouse up, by calling {@link stopTool}. * If you want to handle multiple mouse down-up gestures in one tool activation, * you will need to override this method to only stop the tool when you want. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * By default this method just calls {@link stopTool}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseUp(): void; /** * The diagram will call this method as the mouse wheel is rotated. * Implementations of this method can look at {@link Diagram.lastInput} to get the mouse * event and input state. * * By default this method does nothing. * (But the {@link ToolManager.doMouseWheel} override will call {@link Tool.standardMouseWheel}.) * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseWheel(): void; /** * Called by {@link ToolManager.doMouseDown} and {@link ToolManager.doMouseMove}, * this method determines whether or not to allow pinch zooming from a multi-touch event. * By default this predicate just returns true. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link standardPinchZoomStart} * @see {@link standardPinchZoomMove} */ canStartMultiTouch(): boolean; /** * Initiates pinch-zooming on multi-touch devices. * * This is called by {@link ToolManager.doMouseDown} if the {@link Diagram.lastInput} has {@link InputEvent.isMultiTouch} * set to true and {@link canStartMultiTouch} returns true. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canStartMultiTouch} * @see {@link standardPinchZoomMove} */ standardPinchZoomStart(): void; /** * Continues pinch-zooming (started by {@link standardPinchZoomStart} on multi-touch devices. * * This is called by {@link ToolManager.doMouseMove} if the {@link Diagram.lastInput} has {@link InputEvent.isMultiTouch} * set to true and {@link canStartMultiTouch} returns true. * By default this calls {@link doCancel} in order to cancel the regular tool behavior caused by the multitouch events. * This then calculates the appropriate zoom level and calls {@link CommandHandler.canResetZoom} to decide * whether to call {@link CommandHandler.resetZoom} to actually set {@link Diagram.scale}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canStartMultiTouch} * @see {@link standardPinchZoomStart} */ standardPinchZoomMove(): void; /** * The diagram will call this method upon a key down event. * By default this just calls {@link doCancel} if the key is the ESCAPE key. * Implementations of this method can look at {@link Diagram.lastInput} to get the key. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doKeyDown(): void; /** * The diagram will call this method upon a key up event. * Implementations of this method can look at {@link Diagram.lastInput} to get the key. * * By default this method does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doKeyUp(): void; /** * Call {@link Diagram.startTransaction} with the given transaction name. * This always sets {@link transactionResult} to null. * * This is normally called in an override of {@link doActivate}, if the tool modifies the model, * along with a call to {@link stopTransaction} in an override of {@link doDeactivate}. * Alternatively, you can surround a block of code that sets the {@link transactionResult} * with calls to startTransaction and stopTransaction. * @param tname - a string describing the transaction. * @returns the value of the call to {@link Diagram.startTransaction}. */ startTransaction(tname?: string): boolean; /** * If {@link transactionResult} is null, call {@link Diagram.rollbackTransaction}, * otherwise call {@link Diagram.commitTransaction}. * * This is normally called in an override of {@link doDeactivate}, * if {@link startTransaction} was called in {@link doActivate}. * Alternatively, you can surround a block of code that sets the {@link transactionResult} * with calls to `startTransaction` and `stopTransaction`. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the result of the call to rollback or commit the transaction. */ stopTransaction(): boolean; /** * Implement the standard behavior for selecting parts with the mouse, * depending on the control and shift modifier keys. * * Control-clicking on a part will select it if it wasn't already, * and will deselect if it had been selected. * Shift-clicking on a part will add it to the selection (if it wasn't already). * Otherwise, clicking on a part will select it (if it wasn't already). * * Note that there are restrictions on selection. * For example, a part cannot be selected in this manner if {@link Part.selectable} is false, * or if {@link Diagram.maxSelectionCount} would be exceeded. * * A left click in the background of the diagram with no modifier keys clears the selection. * * This method does not implement any click event behavior -- that is implemented by {@link standardMouseClick}. * * The {@link ClickSelectingTool} calls this method in its override of {@link doMouseUp} in order to change the selection. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ standardMouseSelect(): void; /** * Implement the standard behavior for mouse clicks, * searching for and calling click handler functions on {@link GraphObject}s * or on {@link Diagram}, * and raising the corresponding {@link DiagramEvent}. * * A click on a {@link GraphObject} of the diagram will raise one of the following {@link DiagramEvent}s: * "ObjectSingleClicked", "ObjectDoubleClicked", or "ObjectContextClicked". * This will also look at the corresponding click property: * {@link GraphObject.click}, {@link GraphObject.doubleClick}, or {@link GraphObject.contextClick}. * If the value is a function, this will call it, passing the current {@link InputEvent} * and the GraphObject. * If the value is null, it tries looking at the parent {@link GraphObject.panel}, * and so on, walking up the visual tree until it finds the appropriate function to call. * After calling the click function, if the value of {@link InputEvent.handled} is false, * this method will continue walking up the visual tree looking for more click functions * to call. * Once it has looked at the top-level object (a {@link Part}) * for a click function, this method stops. * * A click in the background of the diagram will raise one of the following {@link DiagramEvent}s: * "BackgroundSingleClicked", "BackgroundDoubleClicked", or "BackgroundContextClicked". * This will also look at the corresponding click property: * {@link Diagram.click}, {@link Diagram.doubleClick}, or {@link Diagram.contextClick}. * If the value is a function, this will call it, passing the current {@link InputEvent}. * * This method is not responsible for selecting or deselecting any parts. * Call {@link standardMouseSelect} for that functionality. * * Note that this calls {@link GraphObject.isEnabledObject} on the target object; * if it returns false, no click action will occur. * * The {@link ClickSelectingTool} calls this method in its override of {@link doMouseUp} in order to raise "click" events. * Note that by default GraphObjects in Layers that are {@link Layer.isTemporary} will not be "clicked". * To change that behavior it is easiest to set {@link GraphObject.isActionable} to true on those objects for which you wish to handle "click" events. * Then the {@link ActionTool}'s {@link doMouseUp} override will raise the standard "click" events. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param navig - An optional custom navigation function to find target objects. * This argument is passed to {@link Diagram.findObjectAt}. * @param pred - An optional custom predicate function to find target objects. * A null value is effectively the same as a function that always returns true. * This argument is passed to {@link Diagram.findObjectAt}, unless the value is undefined, * which means to use a predicate to consider only objects in layers holding permanent objects. * @returns true if {@link InputEvent.handled} had been set to true on the {@link Diagram.lastInput}. */ standardMouseClick(navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null): boolean; /** * Implement the standard behavior for mouse enter, over, and leave events, * where the mouse is moving but no button is pressed. * This should be called by mouse move event handlers when wanting to * detect and invoke mouse enter/over/leave event handlers. * * The {@link GraphObject.mouseEnter} property provides a function to call * when the mouse first enters an object or any of its contained objects * (if the object is actually a {@link Panel}). * * The {@link GraphObject.mouseLeave} property provides a function to call * when the mouse leaves an object and all of its contained objects * (if the object is actually a {@link Panel}). * * The {@link GraphObject.mouseOver} property and {@link Diagram.mouseOver} * properties provide functions to call when the mouse moves but stays * within the same {@link GraphObject} or when the mouse moves in the * background of the {@link Diagram}. * * This method is also responsible for updating the {@link Diagram.currentCursor} * according to the value of {@link GraphObject.cursor} and {@link Diagram.defaultCursor}. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ standardMouseOver(): void; /** * Implement the standard behavior for mouse wheel events. * {@link ToolManager.doMouseWheel} calls this method. * * Turning the mouse wheel if {@link Diagram.allowVerticalScroll} is true * causes the diagram to scroll up or down. * If {@link InputEvent.shift} and {@link Diagram.allowHorizontalScroll} are true, * the diagram scrolls left or right. * * If {@link InputEvent.control} and {@link Diagram.allowZoom} are true, * turning the mouse wheel changes the diagram's scale, * zooming in or out while trying to keep the point in the model * at the same point as the mouse. * * The value of {@link ToolManager.mouseWheelBehavior} affects what operations might occur * upon mouse wheel events. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ standardMouseWheel(): void; /** * This is called to start a new timer to call {@link doWaitAfter} after a given delay. * It first cancels any previously running "WaitAfter" timer, by calling {@link cancelWaitAfter}. * * This is normally used to implement mouse hover and mouse hold events. * If the mouse has moved, it must not have moved beyond the distance as determined by * {@link Tool.isBeyondDragSize} for it be considered "stationary". * So the regular {@link ToolManager.doMouseMove} implementation only calls * this method when the mouse has moved beyond the drag size. * * This method is rarely overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param delay - The delay, in milliseconds. * @param event - An optional event that caused this timer. Defaults to {@link Diagram.lastInput}. * This gets passed on to {@link doWaitAfter}. */ standardWaitAfter(delay: number, event?: InputEvent): void; /** * This is called to cancel any running "WaitAfter" timer. * * This is called when a tool is stopped. * * This method is rarely overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ cancelWaitAfter(): void; /** * This is called a certain delay after a call to {@link standardWaitAfter} if there * has not been any call to {@link cancelWaitAfter}. * The {@link ToolManager} overrides this method in order to implement support for mouse-hover behavior and tooltips. * * By default this does nothing. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param event - The event that caused {@link standardWaitAfter}. */ doWaitAfter(event: InputEvent): void; /** * This convenience function finds the front-most {@link GraphObject} * that is at a given point and that is an element of an {@link Adornment} * that is of a given category. * The tool handle must be an immediate element of the Adornment, * not a GraphObject that is nested within Panels within the Adornment. * * This method is very infrequently overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param p - a Point in document coordinates. * @param category - the required {@link Part.category} of the {@link Adornment}. */ findToolHandleAt(p: Point, category: string): GraphObject | null; /** * Return true when the last mouse point is far enough away from the first mouse down point * to constitute a drag operation instead of just a potential click. * * This uses the value of {@link ToolManager.dragSize}. * On touch devices the value is automatically increased to accommodate the unavoidable movement of fingers. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param first - Point in view coordinates, defaults to {@link Diagram.firstInput}'s {@link InputEvent.viewPoint}. * @param last - Point in view coordinates, defaults to {@link Diagram.lastInput}'s {@link InputEvent.viewPoint}. */ isBeyondDragSize(first?: Point, last?: Point): boolean; /** * Gets or sets the name of this tool. * The default name is an empty string, * but the constructor for each instance of a subclass of Tool will initialize it appropriately. * For example, the name of the {@link DragSelectingTool} is "DragSelecting". * * This name is sometimes used by tools that use {@link Adornment}s as the {@link Part.category} for their Adornments. * It is also sometimes used by tools that conduct transactions as the transaction name. */ get name(): string; set name(value: string); /** * Gets or sets whether this tool can be started by a mouse event. * * Set this to false to prevent {@link canStart} from returning true. * Setting this property to false should prevent this tool from being used in a mode-less fashion * by the {@link ToolManager} with a mouse down/move/up event. * However, even when this property is false, this tool can still be used in a modal fashion: * it can still be started by explicitly setting the * {@link Diagram.currentTool} property to this tool. * * The default value is true. */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * Gets or sets whether this tool is started and is actively doing something. * * You can set this to true after your tool is started (i.e. when it is the * {@link Diagram.currentTool} and {@link doStart} * had been called), but when it is not yet in a state * that it is actually "doing" something, because it is waiting for the right * circumstances. This is typically only important when the tool is used in * a modal fashion. * * The default value is false. * This is normally set by {@link doActivate} and {@link doDeactivate}. */ get isActive(): boolean; set isActive(value: boolean); /** * Gets or sets the name of the transaction to be committed by {@link stopTransaction} * * If null, the transaction will be rolled back. * * If this is non-null at the time of a call to {@link stopTransaction}, * it calls {@link Diagram.commitTransaction} with this transaction name; * if this is null at that time, it calls {@link Diagram.rollbackTransaction}. * * The default value is null; {@link startTransaction} will also set this to null. * Because a value of null when {@link stopTransaction} is called will rollback the transaction, * it is important that your code sets this property to a non-null value when it thinks it has succeeded. * * This property exists so that no matter what execution path occurs to end the usage of a tool, * any ongoing transaction can be properly committed or rolled-back. * Many tools call {@link startTransaction} and {@link stopTransaction}; thus they set this property * for their transaction to be committed. * {@link doCancel} also sets this property to null. */ get transactionResult(): string | null; set transactionResult(value: string | null); } /** * This enumeration specifies possible values for {@link ToolManager.mouseWheelBehavior}. * @since 3.0 * @category Tool */ export declare enum WheelMode { /** * Mouse wheel events scroll the diagram. This is the default. */ Scroll = 1, /** * Mouse wheel events change the scale of the diagram. */ Zoom = 2, /** * Mouse wheel events are ignored, although scrolling or zooming by other means may still be allowed. */ None = 3 } /** * This enumeration specifies possible values for {@link ToolManager.gestureBehavior}. * @since 3.0 * @category Tool */ export declare enum GestureMode { /** * Pointer/touch pinch gestures on the canvas intend to zoom the Diagram. This is the default. */ Zoom = 1, /** * Pointer/touch pinch gestures on the canvas intend to have no effect on the Diagram, but also no effect on the page. */ Cancel = 2, /** * Pointer/touch pinch gestures on the canvas intend to have no effect on the Diagram, but will not be prevented, and may bubble up the page to have other effects (such as zooming the page). */ None = 3 } /** * This special {@link Tool} is responsible for managing all of the Diagram's * mode-less tools, which you can access as the {@link Diagram.toolManager}. * * Mode-less tools are tools that are present in one of the following lists: * {@link mouseDownTools}, {@link mouseMoveTools}, or {@link mouseUpTools}. * This ToolManager tool is normally the {@link Diagram.defaultTool}, * so it is also usually the {@link Diagram.currentTool} when the user is doing "nothing". * * When this tool is running as the current tool, it handles mouse-down, * mouse-move, and mouse-up events and the corresponding touch events. * For each event it iterates over each of the tools in the corresponding list, * calling the tool's {@link Tool.canStart} predicate. * If that predicate returns true, it starts that tool by making it the * diagram's current tool. * It then activates the tool and passes on the event to the tool by calling * the corresponding method (either {@link Tool.doMouseDown}, * {@link Tool.doMouseMove}, or {@link Tool.doMouseUp}). * * Because this tool is typically the one running as the diagram's current tool * when the user isn't "doing" anything, this tool can also handle other events, * such as mouse wheel events and keyboard commands. * * Keyboard events are just passed on to the {@link Diagram.commandHandler}'s * {@link CommandHandler.doKeyDown} or {@link CommandHandler.doKeyUp} method. * * This tool also is responsible for showing tooltips. * Tooltip {@link Adornment}s may be declared as any {@link GraphObject.toolTip}, * or as the {@link Diagram.toolTip} if the mouse or finger remains motionless in the background of the diagram. * You can set {@link toolTipDuration} to control how long the tooltip remains visible after being motionless. * * This tool does not utilize any tool handles. * This tool does not conduct any transactions. * But of course some of the tools that the ToolManager starts can show tool handles and/or * conduct their own transactions. * @category Tool */ export class ToolManager extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link Diagram.toolManager}, which you can modify. * * The {@link Tool.name} of this tool is "ToolManager". * * The constructor produces a ToolManager that manages no tools. * Call {@link initializeStandardTools} to create various tools, * initialize the tool properties such as {@link draggingTool}, * and initialize the three mouse tool lists with those newly created tools. */ constructor(init?: Partial); /** * @deprecated See {@link WheelMode.Scroll}. */ static readonly WheelScroll = WheelMode.Scroll; /** * @deprecated See {@link WheelMode.Zoom}. */ static readonly WheelZoom = WheelMode.Zoom; /** * @deprecated See {@link WheelMode.None}. */ static readonly WheelNone = WheelMode.None; /** * @deprecated See {@link GestureMode.Zoom}. */ static readonly GestureZoom = GestureMode.Zoom; /** * @deprecated See {@link GestureMode.Cancel}. */ static readonly GestureCancel = GestureMode.Cancel; /** * @deprecated See {@link GestureMode.None}. */ static readonly GestureNone = GestureMode.None; /** * Gets or sets the ToolManager's mouse wheel behavior. Allowed values are {@link WheelMode} values. * * The default value is {@link WheelMode.Scroll}. */ get mouseWheelBehavior(): WheelMode; set mouseWheelBehavior(value: WheelMode); /** * Gets or sets the ToolManager's touch pinching behavior. * Allowed values are {@link GestureMode} values. * The default value is {@link GestureMode.Zoom}. * * If you want to control whether a single finger touch movement * causes a pan (i.e. scroll) of the diagram's contents or scrolls the page, * consider either disabling the {@link PanningTool} by setting its property * {@link Tool.isEnabled} to false or by setting {@link PanningTool.bubbles} to true. * */ get gestureBehavior(): GestureMode; set gestureBehavior(value: GestureMode); /** * Initialize the three mouse tool lists with instances of the standard tools. * This adds new instances of tools to the following three mouse tool lists: * {@link mouseDownTools}, {@link mouseMoveTools}, or {@link mouseUpTools}. * This also sets the various tool properties of this ToolManager * to those newly created tools. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ initializeStandardTools(): void; /** * Iterate over the {@link mouseDownTools} list and start the first tool * for which its {@link Tool.canStart} predicate returns true. * * Starting a tool replaces the {@link Diagram.currentTool} with the new tool. * Successfully doing so also activates the new tool by calling {@link Tool.doActivate} * and passes on the mouse-down event to it by calling {@link Tool.doMouseDown}. * * Not finding any startable tools causes this tool manager to activate, * thereby enabling the mouse-move and mouse-up behaviors and starts * detection of a mouse-hold event after {@link holdDelay} milliseconds. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseDown(): void; /** * Iterate over the {@link mouseMoveTools} list and start the first tool * for which its {@link Tool.canStart} predicate returns true. * * Starting a tool replaces the {@link Diagram.currentTool} with the new tool. * Successfully doing so also activates the new tool by calling {@link Tool.doActivate} * and passes on the mouse-move event to it by calling {@link Tool.doMouseMove}. * * If no tool is found and activated, this: * - Calls {@link Tool.standardMouseOver} to invoke any mouse-enter, mouse-over, or mouse-leave functions. * - if the mouse has moved sufficiently, such that {@link Tool.isBeyondDragSize} is true, * this also calls {@link Tool.standardWaitAfter} for a possible call to * {@link doWaitAfter} after {@link hoverDelay} milliseconds. * - Sets the {@link Diagram.lastInput} to bubble. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseMove(): void; /** * Implement the standard behavior for when the mouse has not moved for a period of time. * This is due to an expired timer started by calling {@link Tool.standardWaitAfter}. * * This calls {@link doMouseHover} and, if not mouse-down, {@link doToolTip}. * Afterwards, if the event that called {@link Tool.standardWaitAfter} was a touch event, * this simulates a right click, enabling context menu functionality and other actions on touch devices. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param event - The event that caused {@link standardWaitAfter}. In this override, * if it is a touch event and the {@link Diagram.lastInput} event is not handled ({@link InputEvent.handled} set to false), * then this method will simulate a right click. */ doWaitAfter(event: InputEvent): void; /** * Implement the standard behavior for mouse hover and mouse hold events, * called by {@link doWaitAfter} when the mouse has not moved for a period of time. * * If there has been no mouse down, the timer is set for {@link hoverDelay} milliseconds. * If it executes, it calls any {@link GraphObject.mouseHover} function on the object * at the mouse or on any of its containing panels, * or it calls any {@link Diagram.mouseHover} function for a background mouse-hover event. * * If there had been a mouse down, the timer is set for {@link holdDelay} milliseconds. * If it executes, it calls any {@link GraphObject.mouseHold} function on the object * at the mouse or on any of its containing panels, * or it calls any {@link Diagram.mouseHold} function for a background mouse-held-down event. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseHover(): void; /** * Implement the standard behavior for tooltips, * called by {@link doWaitAfter} when the mouse has not moved for a period of time. * * This looks for a {@link GraphObject} at the latest mouse point. * If it finds an object, it checks for a {@link GraphObject.toolTip}. * If it has none, this method searches up the visual tree for a containing * {@link Panel} that does have a tooltip. * * If it didn't find any object, this looks for a {@link Diagram.toolTip}. * * If it eventually finds a tooltip, this calls {@link showToolTip}. * Otherwise this calls {@link hideToolTip}. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doToolTip(): void; /** * Show a tooltip Adornment or HTMLInfo. * This is called by {@link doToolTip} once that method has found a tooltip to display. * * This calls {@link positionToolTip} to make it easier to customize how the tooltip * is positioned relative to the object with the tooltip. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param tooltip * @param obj - The GraphObject getting the tooltip; this is null if the tooltip is being shown for the diagram background. */ showToolTip(tooltip: Adornment | HTMLInfo, obj: GraphObject | null): void; /** * This is called by {@link showToolTip} to position the part within the viewport. * It normally goes just below the cursor. * But if the mouse is too close to the right edge or the bottom edge of the viewport, * it is positioned left and/or above the cursor. * * This method only operates if the tooltip, an {@link Adornment}, does not have a {@link Adornment.placeholder}. * When there is a {@link Placeholder} in the tooltip, that Adornment is automatically positioned * so that the Placeholder is positioned at the adorned object, the second argument to this method. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * If you override this method to position the tooltip, * the tooltip has already been measured but not arranged, * so you can use its {@link GraphObject.measuredBounds} width and height * but not its {@link GraphObject.actualBounds}. * @virtual * @param tooltip * @param obj - The {@link GraphObject} getting the tooltip, * or null if the tooltip is for the diagram background. */ positionToolTip(tooltip: Adornment, obj: GraphObject | null): void; /** * Hide any tooltip. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ hideToolTip(): void; /** * This read-only property returns the currently showing tooltip, or null if there is none. */ get currentToolTip(): Adornment | HTMLInfo | null; set currentToolTip(value: Adornment | HTMLInfo | null); /** * Iterate over the {@link mouseUpTools} list and start the first tool * for which its {@link Tool.canStart} predicate returns true. * * Starting a tool replaces the {@link Diagram.currentTool} with the new tool. * Successfully doing so also activates the new tool by calling {@link Tool.doActivate} * and passes on the mouse-up event to it by calling {@link Tool.doMouseUp}. * * If no startable tool is found it deactivates this tool manager, * to get ready for a mouse-down and ignore mouse-move and mouse-up events. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseUp(): void; /** * The diagram will call this method as the mouse wheel is rotated. * * By default this just calls {@link Tool.standardMouseWheel}. * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doMouseWheel(): void; /** * This just calls {@link CommandHandler.doKeyDown} on the diagram's {@link Diagram.commandHandler}. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doKeyDown(): void; /** * This just calls {@link CommandHandler.doKeyUp} on the diagram's {@link Diagram.commandHandler}. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doKeyUp(): void; /** * Find a mouse tool of a given name. * This searches the {@link mouseDownTools}, {@link mouseMoveTools}, and {@link mouseUpTools} lists. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param name - the type of tool, such as "Dragging" or "ClickSelecting". * @returns a {@link Tool} whose {@link Tool.name} exactly matches the given name, * or null if no such tool is found in any of the three lists. */ findTool(name: string): Tool | null; /** * Replace a mouse tool of a given name with a new tool, or remove an existing tool (if the *newtool* is null). * This searches the {@link mouseDownTools}, {@link mouseMoveTools}, * and {@link mouseUpTools} lists. * The new tool is inserted into the same list in which the same-named tool is found, * at the same position as the old tool. * However, if no existing tool with the given name is present, this does **not** add the new tool to any list, since it cannot know where it should be added. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param name - the type of tool, such as "Dragging" or "ClickSelecting". * @param newtool - If null, any tool that the search finds will just be removed * from the list in which it was found. * @returns the old tool that was replaced by the new one; this is null if none was found and the new tool was not added to any mouse tool list */ replaceTool(name: string, newtool: Tool): Tool | null; /** * (undocumented) * @param name * @param newtool * @param list */ replaceStandardTool(name: string, newtool: Tool, list: List): void; /** * This read-only property returns the list of {@link Tool}s that might be started upon a mouse or finger press event. * When the ToolManager handles a mouse-down or touch-down event in {@link doMouseDown}, * it searches this list in order, starting the first tool for which * {@link Tool.canStart} returns true. * * This list may be modified, but it must not be modified while any tool * is handling events. * * {@link initializeStandardTools} installs the following tools, in order: * - {@link actionTool}, an {@link ActionTool} * - {@link relinkingTool}, a {@link RelinkingTool} * - {@link linkReshapingTool}, a {@link LinkReshapingTool} * - {@link rotatingTool}, a {@link RotatingTool} * - {@link resizingTool}, a {@link ResizingTool} */ get mouseDownTools(): List; /** * This read-only property returns the list of {@link Tool}s that might be started upon a mouse or finger move event. * When the ToolManager handles a mouse-move or touch-move event in {@link doMouseMove}, * it searches this list in order, starting the first tool for which * {@link Tool.canStart} returns true. * * This list may be modified, but it must not be modified while any tool * is handling events. * * {@link initializeStandardTools} installs the following tools, in order: * - {@link linkingTool}, a {@link LinkingTool} * - {@link draggingTool}, a {@link DraggingTool} * - {@link dragSelectingTool}, a {@link DragSelectingTool} * - {@link panningTool}, a {@link PanningTool} */ get mouseMoveTools(): List; /** * This read-only property returns the list of {@link Tool}s that might be started upon a mouse or finger up event. * When the ToolManager handles a mouse-up or touch-up event in {@link doMouseUp}, * it searches this list in order, starting the first tool for which * {@link Tool.canStart} returns true. * * This list may be modified, but it must not be modified while any tool * is handling events. * * {@link initializeStandardTools} installs the following tools, in order: * - {@link contextMenuTool}, a {@link ContextMenuTool} * - {@link textEditingTool}, a {@link TextEditingTool} * - {@link clickCreatingTool}, a {@link ClickCreatingTool} * - {@link clickSelectingTool}, a {@link ClickSelectingTool} */ get mouseUpTools(): List; /** * Gets or sets the time between when the mouse stops moving and a hover event, * in milliseconds. This value affects the delay before {@link GraphObject.toolTip}s are shown. * The default value is 850 milliseconds. * * Set {@link toolTipDuration} to control how long a tooltip will remain visible. */ get hoverDelay(): number; set hoverDelay(value: number); /** * Gets or sets the time between when the mouse stops moving and a hold event, * in milliseconds. * The default value is 850 milliseconds. */ get holdDelay(): number; set holdDelay(value: number); /** * Gets or sets the distance in view coordinates within which a mouse down-and-up is considered a click and beyond which a mouse movement is considered a drag. * The default value is 2 pixels horizontally and vertically for mouse events, and increases by 6 pixels for touch events. * This value is used by {@link Tool.isBeyondDragSize}. */ get dragSize(): Size; set dragSize(value: Size); /** * Gets or sets how long a tool tip is visible. * The default value is 5000 milliseconds. * * This is used by {@link showToolTip} to determine how long to wait before calling {@link hideToolTip}. * * Set {@link hoverDelay} to control how long the mouse should stay stationary before it shows a tooltip. */ get toolTipDuration(): number; set toolTipDuration(value: number); /** * Gets or sets the mode-less {@link ActionTool}, normally one of the {@link mouseDownTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get actionTool(): ActionTool; set actionTool(value: ActionTool); /** * Gets or sets the mode-less {@link RelinkingTool}, normally one of the {@link mouseDownTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get relinkingTool(): RelinkingTool; set relinkingTool(value: RelinkingTool); /** * Gets or sets the mode-less {@link LinkReshapingTool}, normally one of the {@link mouseDownTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get linkReshapingTool(): LinkReshapingTool; set linkReshapingTool(value: LinkReshapingTool); /** * Gets or sets the mode-less {@link ResizingTool}, normally one of the {@link mouseDownTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get resizingTool(): ResizingTool; set resizingTool(value: ResizingTool); /** * Gets or sets the mode-less {@link RotatingTool}, normally one of the {@link mouseDownTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get rotatingTool(): RotatingTool; set rotatingTool(value: RotatingTool); /** * Gets or sets the mode-less {@link LinkingTool}, normally one of the {@link mouseMoveTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get linkingTool(): LinkingTool; set linkingTool(value: LinkingTool); /** * Gets or sets the mode-less {@link DraggingTool}, normally one of the {@link mouseMoveTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get draggingTool(): DraggingTool; set draggingTool(value: DraggingTool); /** * Gets or sets the mode-less {@link DragSelectingTool}, normally one of the {@link mouseMoveTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get dragSelectingTool(): DragSelectingTool; set dragSelectingTool(value: DragSelectingTool); /** * Gets or sets the mode-less {@link PanningTool}, normally one of the {@link mouseMoveTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get panningTool(): PanningTool; set panningTool(value: PanningTool); /** * Gets or sets the mode-less {@link ContextMenuTool}, normally one of the {@link mouseUpTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get contextMenuTool(): ContextMenuTool; set contextMenuTool(value: ContextMenuTool); /** * Gets or sets the mode-less {@link TextEditingTool}, normally one of the {@link mouseUpTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get textEditingTool(): TextEditingTool; set textEditingTool(value: TextEditingTool); /** * Gets or sets the mode-less {@link ClickCreatingTool}, normally one of the {@link mouseUpTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get clickCreatingTool(): ClickCreatingTool; set clickCreatingTool(value: ClickCreatingTool); /** * Gets or sets the mode-less {@link ClickSelectingTool}, normally one of the {@link mouseUpTools}. * * You can disable this tool by setting its {@link Tool.isEnabled} property to false. */ get clickSelectingTool(): ClickSelectingTool; set clickSelectingTool(value: ClickSelectingTool); } /** * The DraggingTool is used to move or copy selected parts with the mouse. * This sets the {@link Part.location} property; you may want to save the location to the model * by using a TwoWay {@link Binding} on the "location" property in your Parts/Nodes/Groups templates. * * Dragging the selection moves parts for which {@link Part.canMove} is true. * If the user holds down the Control key (Option key on Mac), this tool will make a copy of the parts being dragged, * for those parts for which {@link Part.canCopy} is true. * * When the drag starts it calls {@link computeEffectiveCollection} to find the actual collection * of {@link Part}s to be dragged. * Normally this collection includes not only the {@link Diagram.selection}, but also parts that belong * to those selected parts, such as members of groups. * If {@link dragsTree} is true, the effective collection also includes all of the nodes and links that * constitute the subtree starting from selected nodes. * The result of {@link computeEffectiveCollection} is not a {@link Set | go.Set} but a {@link Map | go.Map} * which remembers the original {@link Part.location} for all of the dragged parts. * This map is saved as the value of {@link draggedParts}. * * During the drag if the user holds down the Control/Option key this tool makes a copy of the {@link draggedParts} * and proceeds to drag it around. * (It only copies the {@link Diagram.selection}, not the whole effective collection, * if {@link copiesEffectiveCollection} is false.) * The collection of copied parts is held by {@link copiedParts}. * It too is a {@link Map | go.Map} remembering the original locations of the parts. * {@link copiedParts} will be null when this tool is moving (not copying) at the moment. * * Each Part's movement is limited by the {@link Diagram.computeMove} method. * By default it limits the {@link Part.location} to be within the bounds given by {@link Part.minLocation} and {@link Part.maxLocation}. * (Those default to minus Infinity to plus Infinity.) * As a further convenience, the value of NaN in minLocation and maxLocation cause {@link Diagram.computeMove} to use the * part's current location. * So, for example, an easy way to declare that the user may only drag a node horizontally is to just set: * ```js * new go.Node( * . . . * { minLocation: new go.Point(-Infinity, NaN), maxLocation: new go.Point(Infinity, NaN) }, * . . . * ) * ``` * * If you set {@link isGridSnapEnabled} to true, dragged or copied parts will be snapped to points on a grid. * The snapping occurs continuously during a drag unless you set {@link isGridSnapRealtime} to false. * Normally the grid points come from the {@link Diagram.grid}, even if that grid is not {@link GraphObject.visible}. * However you can override those grid's properties for the snapping grid cell size and offset * by setting the properties here: {@link gridSnapCellSize} and {@link gridSnapOrigin}. * This computes the point to snap to for each dragged part. * The resulting point is used as the new {@link Part.location}. * * For the most general control over where a part may be dragged, either set the {@link Part.dragComputation} property * or override {@link Diagram.computeMove}. * For the common case of wanting to keep member nodes within the {@link Group} that they are members of, * you can do something like: * ```js * // this is a Part.dragComputation function for limiting where a Node may be dragged * function stayInGroup(part, pt, gridpt) { * // don't constrain top-level nodes * const grp = part.containingGroup; * if (grp === null) return pt; * // try to stay within the background Shape of the Group * const back = grp.resizeObject; * if (back === null) return pt; * // allow dragging a Node out of a Group if the Shift key is down * if (part.diagram.lastInput.shift) return pt; * const p1 = back.getDocumentPoint(go.Spot.TopLeft); * const p2 = back.getDocumentPoint(go.Spot.BottomRight); * const b = part.actualBounds; * const loc = part.location; * // find the padding inside the group's placeholder that is around the member parts * const m = grp.placeholder.padding; * // now limit the location appropriately, assuming no grid-snapping * const x = Math.max(p1.x + m.left, Math.min(pt.x, p2.x - m.right - b.width - 1)) + (loc.x-b.x); * const y = Math.max(p1.y + m.top, Math.min(pt.y, p2.y - m.bottom - b.height - 1)) + (loc.y-b.y); * return new go.Point(x, y); * } * ``` * Note that this expects there to be a "SHAPE" object within the Group's visual tree that delimits * where the part may be dragged within the group. * This also expects that {@link Group.computesBoundsIncludingLinks} is false. * Then in your node template(s), just set: * ```js * new go.Node( * . . ., * { dragComputation: stayInGroup }, * . . . * ) * ``` * * This tool does not utilize any {@link Adornment}s or tool handles. * If the drag is successful, it raises the "SelectionMoved" or "SelectionCopied" {@link DiagramEvent} * and produces a "Move" or a "Copy" transaction. * * If you want to programmatically start a new user's dragging of a particular existing node, * you can make sure that node is selected, set the {@link currentPart} property, and then start and activate the tool. * ```js * const node = ...; * myDiagram.select(node); // in this case the only selected node * const tool = myDiagram.toolManager.draggingTool; * tool.currentPart = node; // the DraggingTool will not call standardMouseSelect * myDiagram.currentTool = tool; // starts the DraggingTool * tool.doActivate(); // activates the DraggingTool * ``` * @category Tool */ export class DraggingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.draggingTool}, which you can modify. * * The {@link Tool.name} of this tool is "Dragging". */ constructor(init?: Partial); /** * Gets or sets whether for any internal copying operation is permitted by control-drag-and-drop (or alt-drag-and-drop on Mac). * This property affects the behavior of {@link mayCopy}, * but does not affect whether copied objects may be dropped into this diagram from a different diagram. * * The default value is true. * Setting this property does not raise any events. */ get isCopyEnabled(): boolean; set isCopyEnabled(value: boolean); /** * Gets or sets whether for a copying operation the extended selection * is copied or only the selected parts. * The default value is true. * Setting this property does not raise any events. * * The {@link CommandHandler.copiesConnectedLinks} property serves a similar role for the {@link CommandHandler.copySelection} command, * when the user types control-C to copy the currently selected parts. */ get copiesEffectiveCollection(): boolean; set copiesEffectiveCollection(value: boolean); /** * Gets or sets the {@link DraggingTool}'s {@link DraggingOptions} instance, which controls several dragging properties. * * Several DraggingTool properties are just convenience properties: * - {@link isGridSnapEnabled} * - {@link isGridSnapRealtime} * - {@link gridSnapCellSize} * - {@link gridSnapCellSpot} * - {@link gridSnapOrigin} * - {@link dragsLink} * - {@link dragsTree} * * Setting any of these properties really sets the corresponding dragOptions property. * * Setting this property does not raise any events. * @since 2.0 */ get dragOptions(): DraggingOptions; set dragOptions(value: DraggingOptions); /** * Gets or sets whether the {@link DraggingTool} snaps objects to grid points. * Whether the snapping movement of the dragged parts occurs during the drag or only upon a drop * is determined by the value of {@link isGridSnapRealtime}. * * This property does not affect dragging disconnected links, * but those links do respect the {@link Part.dragComputation}, which can be used to snap them. * * By default this property is false. * Setting this property does not raise any events. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get isGridSnapEnabled(): boolean; set isGridSnapEnabled(value: boolean); /** * In 3.0 this is superceded by {@link Router.isRealtime}, and setting this property attempts to set that property * on the "AvoidsLinks" {@link Router}. * * Gets or sets whether link routing takes some short-cuts during dragging. * When false Links whose routing is AvoidsNodes are not routed to avoid Nodes, in order to improve dragging performance. * The default value is true. * @deprecated See {@link Router.isRealtime} */ get isComplexRoutingRealtime(): boolean; set isComplexRoutingRealtime(value: boolean); /** * Gets or sets whether the {@link DraggingTool} snaps objects to grid points during the drag. * This property is ignored unless {@link isGridSnapEnabled} is true. * By default this property is true; when false parts are only snapped to grid locations upon the drop (i.e. mouse-up). * Setting this property does not raise any events. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get isGridSnapRealtime(): boolean; set isGridSnapRealtime(value: boolean); /** * Gets or sets the size of the grid cell used when snapping during a drag * if the value of {@link isGridSnapEnabled} is true. * By default this property is the Size(NaN, NaN), which causes this tool to use the {@link Panel.gridCellSize} value of the {@link Diagram.grid}. * Setting this property does not raise any events. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get gridSnapCellSize(): Size; set gridSnapCellSize(value: Size); /** * Gets or sets the {@link Spot} that specifies what point in the grid cell dragged parts snap to, * if the value of {@link isGridSnapEnabled} is true. * By default this property is {@link Spot.TopLeft}: * node locations will snap exactly to the grid point. * Setting this property does not raise any events. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get gridSnapCellSpot(): Spot; set gridSnapCellSpot(value: Spot); /** * Gets or sets the snapping grid's origin point, in document coordinates, * if the value of {@link isGridSnapEnabled} is true. * By default this property is the Point(NaN, NaN), * which causes this tool to use the {@link Panel.gridOrigin} value from the {@link Diagram.grid}. * Setting this property does not raise any events. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get gridSnapOrigin(): Point; set gridSnapOrigin(value: Point); /** * Gets or sets whether the user can drag a single {@link Link}, * disconnecting it from its connected nodes and possibly connecting it * to valid ports when the link is dropped. * The default value is false. * Setting this property does not raise any events. * * In order to avoid too many cases of having both ends of a dragged Link connect to the same node (if allowed), * it is commonplace to decrease the {@link LinkingBaseTool.portGravity} to a smaller value such as 10 or 20. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get dragsLink(): boolean; set dragsLink(value: boolean); /** * Gets or sets whether moving or copying a node also includes all of the * node's tree children and their descendants, along with the links to those additional nodes. * The default value is false. * Setting this property does not raise any events. * * The {@link CommandHandler.copiesTree} property serves a similar role for the {@link CommandHandler.copySelection} command, * when the user types control-C to copy the currently selected parts. * * This property is a convenience getter/setter, and sets a value on {@link dragOptions}. */ get dragsTree(): boolean; set dragsTree(value: boolean); /** * The cursor to show when a drop is allowed and will result in a copy. * This defaults to 'copy'. * Read more about cursors at {@link Diagram.currentCursor} * @since 2.2 */ get copyCursor(): string; set copyCursor(c: string); /** * The cursor to show when a drop is allowed and will result in a move. * This defaults to the empty string, which refers to the {@link Diagram.defaultCursor}. * Read more about cursors at {@link Diagram.currentCursor} * @since 2.2 */ get moveCursor(): string; set moveCursor(c: string); /** * The cursor to show when a drop is not allowed. * This defaults to 'no-drop'. * Read more about cursors at {@link Diagram.currentCursor} * @since 2.2 */ get nodropCursor(): string; set nodropCursor(c: string); /** * Gets or sets the {@link Part} found at the mouse point. * This is normally set by a call to {@link standardMouseSelect}. */ get currentPart(): Part | null; set currentPart(value: Part | null); /** * Gets or sets the collection of {@link Part}s that this tool has copied. * The value is a {@link Map | go.Map} mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. * The value is null when moving instead of copying. * * {@link draggedParts} provides the map of Parts that are being moved and from which this collection was copied. */ get copiedParts(): Map | null; set copiedParts(value: Map | null); /** * Gets or sets the collection of {@link Part}s being moved. * The value is a {@link Map | go.Map} mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. * * {@link copiedParts} provides the map of Parts that have been copied during a copying operation, if any. */ get draggedParts(): Map | null; set draggedParts(value: Map | null); /** * (undocumented) * This read-only property returns a {@link Set | go.Set} that holds all of the Parts that are currently being dragged for either copying or moving. * @returns Returns the {@link Map.toKeySet} of either {@link copiedParts} or {@link draggedParts}, or else an empty Set. */ get draggingParts(): Set; set draggedLink(value: Link | null); set isDragOutStarted(value: boolean); /** * Gets or sets the mouse point from which parts start to move. * The value is a Point in document coordinates. * This property is normally set to the diagram's mouse-down point in {@link doActivate}, * but may be set to a different point if parts are being copied from a different control. * Setting this property does not raise any events. */ get startPoint(): Point; set startPoint(value: Point); /** * On touch gestures only, this property gets or sets the time in milliseconds * for which the mouse must be stationary before this tool can be started. * The default value is 100 milliseconds. * Setting this property does not raise any events. */ get delay(): number; set delay(value: number); /** * This tool can run if the diagram allows selection and moves/copies/dragging-out, * if the mouse has moved far enough away to be a drag and not a click, * and if {@link findDraggablePart} has found a selectable part at the mouse-down point. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Return the selectable and movable/copyable {@link Part} at the mouse-down point. * This is called by {@link canStart} to decide if this tool is ready to run. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ findDraggablePart(): Part | null; /** * This override prevents the Control modifier unselecting an already selected part. * This also remembers the selectable {@link currentPart} at the current mouse point. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ standardMouseSelect(): void; /** * Start the dragging operation. * This calls {@link computeEffectiveCollection} and saves the result as {@link draggedParts}. * * This starts a "Drag" transaction. * Depending on what happens, the transaction may be finished as a "Move" or a "Copy" * transaction, or it may be rolled-back if the tool is cancelled. * * Normally when this method is called the value of {@link currentPart} will be null, * in which case this will call {@link Tool.standardMouseSelect} which will set {@link currentPart}. * But if when this method is called the value of {@link currentPart} has already been set * because the programmer wants the user to start dragging that Part, * then this method will not need to call {@link Tool.standardMouseSelect} because * the Part(s) to be selected and dragged have already been determined by the caller. */ doActivate(): void; /** * @param link * (undocumented) * This predicate is passed the single Link that is starting to be dragged when {@link dragsLink} is true. * By default this function ignores the link and only checks whether {@link Diagram.allowRelink} is true. */ mayDragLink(link: Link): boolean; /** * This just calls {@link CommandHandler.computeEffectiveCollection} and remains for compatibility. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param parts - A {@link Set | go.Set} or {@link List} of {@link Part}s. * @param options - Potential options for the collection computation * @returns a Map mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. */ computeEffectiveCollection(parts: Iterable, options: DraggingOptions): Map; /** * Stop the dragging operation by stopping the transaction and cleaning up any temporary state. */ doDeactivate(): void; /** * This calls the super {@link Tool.stopTransaction} method, and if the result is `true`, * attempts to optimize the transaction by removing all changes except the first and last * by calling {@link Transaction.optimize}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the result of the call to rollback or commit the transaction. */ stopTransaction(): boolean; /** * Abort any dragging operation. */ doCancel(): void; /** * Handle switching between copying and moving modes as the Control/Option key is pressed or released. */ doKeyDown(): void; /** * Handle switching between copying and moving modes as the Control/Option key is pressed or released. */ doKeyUp(): void; /** * Move a collection Map of {@link Part}s by a given offset. * * If *check* is true this respects the {@link Part.canMove} predicate for {@link Node}s or simple {@link Part}s * when this is the {@link Diagram.currentTool}. * It also respects {@link isGridSnapEnabled} in order to try to automatically snap part locations to a grid. * And it also uses the {@link Part.dragComputation} function, if any, to determine the new location for each part. * * The first argument is a {@link Map | go.Map} as produced by {@link computeEffectiveCollection}, * not a {@link List} or {@link Set | go.Set} or {@link Iterator} of Parts. * Call {@link Diagram.moveParts} if you want to move a simple collection of Parts without having to create the argument Map. * @virtual * @param parts - a Map mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. * @param offset - The offset, before snapping, to move parts. * This offset reflects the total amount moved during tool operation, * based on original Part locations remembered when the DraggingTool activated. * @param check - Whether to check {@link Part.canMove} on each part. The default value is false. */ moveParts(parts: Map, offset: Point, check?: boolean): void; /** * (undocumented) * @virtual * @param pt */ protected findDragOverObject(pt: Point): GraphObject | null; /** * Perform any additional side-effects during a drag, whether an internal move or copy or an external drag, * that may affect the existing non-moved object(s). * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pt - a Point in document coordinates. * @param obj - the {@link GraphObject} at the point, * excluding what is being dragged or temporary objects; * the argument may be null if the drag is occurring in the background of the diagram. * Use {@link GraphObject.part} to get the {@link Node} or {@link Part} at the root of * the visual tree of the stationary object. */ doDragOver(pt: Point, obj: GraphObject | null): void; /** * Perform any additional side-effects after a drop, whether an internal move or copy or an external drop, * that may affect the existing non-moved object(s). * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pt - a Point in document coordinates. * @param obj - the {@link GraphObject} where the drop occurred, * excluding what was dropped or temporary objects; * the argument may be null if the drop occurred in the background of the diagram. * Use {@link GraphObject.part} to get the {@link Node} or {@link Part} at the root of * the visual tree of the stationary object. */ doDropOnto(pt: Point, obj: GraphObject | null): void; /** * Move the {@link draggedParts} (or if copying, the {@link copiedParts}) to follow the current mouse point. * * If this creates any temporary parts, by default it adds them to the Tool layer. * * This calls {@link doDragOver} for any side-effects on stationary parts. */ doMouseMove(): void; /** * On a mouse-up finish moving or copying the effective selection. * * This calls {@link doDropOnto} for any side-effects on stationary parts. * * This also updates the diagram's bounds, * raises a "SelectionCopied" or "SelectionMoved" DiagramEvent, and stops this tool. * * This method also raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed in a "Drag" transaction, but the "ChangedSelection" event is raised outside the transaction. */ doMouseUp(): void; /** * (undocumented) * @virtual * @param e * @param modelpt * @param overdiag - the diagram attached to the target of the mouse move event, if any. */ simulatedMouseMove(e: Event | Touch | null, modelpt: Point, overdiag: Diagram | null): boolean; /** * (undocumented) * @virtual * @param e * @param modelpt * @param curdiag */ simulatedMouseUp(e: Event | Touch | null, modelpt: Point, curdiag: Diagram | null): boolean; /** * This predicate is true when the diagram allows objects to be copied and inserted, * and some object in the selection is copyable, * and the user is holding down the Control key (Option key on Mac). * * This method may be overridden, although in most cases it is easiest to set {@link Part.copyable}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ mayCopy(): boolean; /** * This predicate is true when the diagram allows objects to be moved, * and some object in the selection is movable. * * This method may be overridden, although in most cases it is easiest to set {@link Part.movable}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ mayMove(): boolean; /** * This method computes the new location for a {@link Node} or simple {@link Part}, * given a new desired location and an optional Map of dragged parts, * taking any grid-snapping into consideration, * any {@link Part.dragComputation} function, * and any {@link Part.minLocation} and {@link Part.maxLocation}. * * This just calls {@link Diagram.computeMove} and remains for compatibility. * * This method may be overridden, but should usually be overridden on Diagram. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param n - the Node or simple Part that is being moved * @param newloc - the proposed new location * @param draggedparts - an optional Map mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. * @param result - an optional Point that is modified and returned * @returns the possibly grid-snapped computed Point that is within the minimum and maximum permitted locations */ computeMove(n: Part, newloc: Point, draggedparts?: Map | null, result?: Point): Point; } /** * This abstract class is the base class for the {@link LinkingTool} and {@link RelinkingTool} classes. * * This class includes properties for defining and accessing any temporary nodes and temporary link * that are used during any linking operation, as well as access to the existing diagram's nodes and link * (if any) that are involved with the linking operation. *

* For a general discussion of link routing, see: * Introduction to Links, * Introduction to Link Labels, and * Introduction to Link Connection Points. * For customizing the linking tools, see Introduction to the Linking Tools. * For customizing the reshaping of Links, see Introduction to the LinkReshapingTool. * For a general discussion of validation, see Introduction to Validation. * @category Tool */ export abstract class LinkingBaseTool extends Tool { /** * Don't construct this directly -- this is an abstract class. */ constructor(); /** * Gets or sets the distance at which link snapping occurs. * The default value is 100.0. * The value must be non-negative. * Setting this property does not raise any events. */ get portGravity(): number; set portGravity(value: number); /** * Gets or sets whether it is valid to have partly or completely unconnected links. * * The default value is false -- the user cannot draw or reconnect a link to "nowhere". * Setting this property does not raise any events. */ get isUnconnectedLinkValid(): boolean; set isUnconnectedLinkValid(value: boolean); /** * Gets or sets the cursor used during the linking or relinking operation. * This defaults to 'pointer'. * Read more about cursors at {@link Diagram.currentCursor} * @since 2.2 */ get linkingCursor(): string; set linkingCursor(c: string); /** * Gets or sets the temporary {@link Link} that is shown while the user is drawing or reconnecting a link. * Setting this property does not raise any events. */ get temporaryLink(): Link; set temporaryLink(value: Link); /** * Gets or sets the temporary {@link Node} at the "from" end of the {@link temporaryLink} * while the user is drawing or reconnecting a link. * Setting this property does not raise any events. */ get temporaryFromNode(): Node; set temporaryFromNode(value: Node); /** * Gets or sets the {@link GraphObject} that is the port at the "from" end of the {@link temporaryLink} * while the user is drawing or reconnecting a link. * Setting this property does not raise any events. */ get temporaryFromPort(): GraphObject; set temporaryFromPort(value: GraphObject); /** * Gets or sets the temporary {@link Node} at the "to" end of the {@link temporaryLink} * while the user is drawing or reconnecting a link. * Setting this property does not raise any events. */ get temporaryToNode(): Node; set temporaryToNode(value: Node); /** * Gets or sets the {@link GraphObject} that is the port at the "to" end of the {@link temporaryLink} * while the user is drawing or reconnecting a link. * Setting this property does not raise any events. */ get temporaryToPort(): GraphObject; set temporaryToPort(value: GraphObject); /** * Gets or sets the original {@link Link} being reconnected by the {@link RelinkingTool}. * Setting this property does not raise any events. */ get originalLink(): Link | null; set originalLink(value: Link | null); /** * Gets or sets the original {@link Node} from which the new link is being drawn * or from which the {@link originalLink} was connected when being relinked. * Setting this property does not raise any events. */ get originalFromNode(): Node | null; set originalFromNode(value: Node | null); /** * Gets or sets the {@link GraphObject} that is the port in the {@link originalFromNode}. * Setting this property does not raise any events. */ get originalFromPort(): GraphObject | null; set originalFromPort(value: GraphObject | null); /** * Gets or sets the original {@link Node} to which the new link is being drawn * or to which the {@link originalLink} was connected when being relinked. * Setting this property does not raise any events. */ get originalToNode(): Node | null; set originalToNode(value: Node | null); /** * Gets or sets the {@link GraphObject} that is the port in the {@link originalToNode}. * Setting this property does not raise any events. */ get originalToPort(): GraphObject | null; set originalToPort(value: GraphObject | null); /** * Gets whether the linking operation is in the forwards direction, * connecting from the "From" port to the "To" port. * @readonly */ get isForwards(): boolean; set isForwards(value: boolean); /** * Gets or sets a proposed {@link GraphObject} port for connecting a link. * Whether this is a "to" port or a "from" port depends on the direction * ({@link isForwards}) in which the link is being drawn or reconnected. * * This is set when the mouse is being dragged and when a mouse-up event occurs * with the result of a call to {@link findTargetPort}. * Setting this property does not raise any events. */ get targetPort(): GraphObject | null; set targetPort(value: GraphObject | null); /** * Make a temporary port look and act like a real one. * * This is called by {@link doMouseMove} as the tool finds new valid target ports. * If {@link findTargetPort} returns null, it calls {@link setNoTargetPortProperties} instead. * * If the {@link portTargeted} property is a function, that function is called. * It is easier to customize the behavior by setting that functional property than it is to override * this method and the {@link setNoTargetPortProperties} method. * But you may want to call this method to get the standard behavior for dynamically adapting * the temporary node/port to "act like" the target port. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param realnode * @param realport * @param tempnode * @param tempport * @param toend */ protected copyPortProperties(realnode: Node | null, realport: GraphObject | null, tempnode: Node, tempport: GraphObject, toend: boolean): void; /** * Reset a temporary port's properties to neutral values when there is no target port. * * This is called by {@link doMouseMove} when the tool finds no new valid target port. * If {@link findTargetPort} returns non-null, it calls {@link copyPortProperties} instead. * * If the {@link portTargeted} property is a function, that function is called with null values as the first two arguments. * It is easier to customize the behavior by setting that functional property than it is to override * this method and the {@link copyPortProperties} method. * But you may want to call this method to get the standard behavior for dynamically adapting * the temporary node/port to "act like" it is not connecting with any target port. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param tempnode * @param tempport * @param toend */ protected setNoTargetPortProperties(tempnode: Node, tempport: GraphObject, toend: boolean): void; /** * Mouse movement results in a temporary node moving to where a valid target port is located, * or to where the mouse is if there is no valid target port nearby. * * This calls {@link findTargetPort} to update the {@link targetPort} * given the new mouse point. * If a valid target port is found this moves the temporary node/port and * makes them appear like the target node/port by calling {@link copyPortProperties}. * If no valid target port is found, this moves the temporary node to * where the mouse currently is and removes any node/port appearance, * by calling {@link setNoTargetPortProperties}. * * This method may be overridden, but we recommend that you call this base method. */ doMouseMove(): void; /** * Find a port with which the user could complete a valid link. * * This finds objects near to the current mouse point for which a valid link connection is possible. * * For each port element found, this calls {@link isValidLink} to find out if a link between * the original node/port and the found node/port would be valid. * The result is saved in a cache for faster decisions later during operation of this tool. * The closest valid port is returned. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param toend - true if looking for a "to" port. * @returns a valid port, or null if no such port is near the current mouse point * within the {@link portGravity} distance. */ findTargetPort(toend: boolean): GraphObject | null; /** * This predicate is true if it is permissible to connect a link from a given node/port. * This is called by {@link isValidLink}. *

* For a more general discussion of validation, see Introduction to Validation. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromnode * @param fromport * @returns False if the node is in a {@link Layer} that does not {@link Layer.allowLink}. * False if the port's {@link GraphObject.fromLinkable} is either false or null. * False if the number of links connected to the port would exceed the port's {@link GraphObject.fromMaxLinks}. * Otherwise true. */ isValidFrom(fromnode: Node | null, fromport: GraphObject | null): boolean; /** * This predicate is true if it is permissible to connect a link to a given node/port. * This is called by {@link isValidLink}. *

* For a more general discussion of validation, see Introduction to Validation. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param tonode * @param toport * @returns False if the node is in a {@link Layer} that does not {@link Layer.allowLink}. * False if the port's {@link GraphObject.toLinkable} is either false or null. * False if the number of links connected from the port would exceed the port's {@link GraphObject.toMaxLinks}. * Otherwise true. */ isValidTo(tonode: Node | null, toport: GraphObject | null): boolean; /** * This predicate is true if both argument ports are in the same {@link Node}. * This is called by {@link isValidLink}. * * This method may be overridden, but we recommend that you call this base method. * It is rare that you will want to override this method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromport * @param toport */ isInSameNode(fromport: GraphObject | null, toport: GraphObject | null): boolean; /** * This predicate is true if there is a link in the diagram going from the given port to the given port. * This is called by {@link isValidLink}. * * This method may be overridden, but we recommend that you call this base method. * It is rare that you will want to override this method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromport * @param toport */ isLinked(fromport: GraphObject | null, toport: GraphObject | null): boolean; /** * This predicate should be true when it is logically valid to connect a new link from * one node/port to another node/port. * When this is called by the {@link RelinkingTool}, that tool sets {@link originalLink} * to be the {@link Link} being reconnected. *

* For a more general discussion of validation, see Introduction to Validation. * * This method may be overridden, although it is usually much easier to just set {@link linkValidation} * or {@link Node.linkValidation} in order to add some application-specific link validation. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromnode - the "from" {@link Node}. * @param fromport - the "from" {@link GraphObject} port. * @param tonode - the "to" {@link Node}. * @param toport - the "to" {@link GraphObject} port. * @returns False if {@link isValidFrom} is false for the "from" node/port. * False if {@link isValidTo} is false for the "to" node/port. * False if {@link isInSameNode} is true unless {@link GraphObject.fromLinkableSelfNode} * and {@link GraphObject.toLinkableSelfNode} are true for the two ports. * False if {@link isLinked} is true unless {@link GraphObject.fromLinkableDuplicates} * and {@link GraphObject.toLinkableDuplicates} are true for the two ports. * False if trying to link to the link's own label node(s). * If {@link Node.linkValidation} is a predicate on either or both of the "from" node and the "to" node, * the predicate is called and if it returns false, this predicate returns false. * If {@link linkValidation} is a predicate and if it returns false, this predicate returns false. * Otherwise this predicate is true. */ isValidLink(fromnode: Node | null, fromport: GraphObject | null, tonode: Node | null, toport: GraphObject | null): boolean; /** * Checks whether a proposed link would be valid according to {@link Diagram.validCycle}. * This does not distinguish between different ports on a node, so this method does not need to take port arguments. * This is called by {@link isValidLink}. * * This method may be overridden, but we recommend that you call this base method. * It is rare that you will want to override this method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param from * @param to * @param ignore - may be null; this is useful during relinking to ignore the {@link originalLink} */ isValidCycle(from: Node | null, to: Node | null, ignore?: Link | null): boolean; /** * Gets or sets a predicate that determines whether or not a new link between two ports would be valid. * This predicate is called in addition to the normal link checking performed by {@link isValidLink} * and any {@link Node.linkValidation} predicates on the "from" and "to" nodes. * When relinking, the {@link Link} being considered for reconnection is passed as the fifth argument. * The default predicate is null, which is equivalent to simply returning true. *

* For a more general discussion of validation, see Introduction to Validation. * * The function, if supplied, must not have any side-effects. */ get linkValidation(): ((fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean) | null; set linkValidation(value: ((fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean) | null); /** * Gets or sets a function that is called as the tool targets the nearest valid port. * The first two arguments specify the port by providing the {@link Node} that it is in * and the {@link GraphObject} that is the actual port object. * The next two arguments are the temporary port that has been moved and styled to be like the valid port. * These values will be either the {@link temporaryToNode} and {@link temporaryToPort} * or the {@link temporaryFromNode} and {@link temporaryFromPort}, depending on * which end of the temporary link is being updated. * The fifth argument is true if the target port represents a potential "to" end of a link; * it is false if it is for the "from" end of a link. * * When there is no valid port within the {@link portGravity}, the first two arguments are null. * * The function, if supplied, must not add or remove any links or nodes or port objects, * nor may it change the validity of any potential link connection. */ get portTargeted(): ((node: Node | null, port: GraphObject | null, tempNode: Node, tempPort: GraphObject, toEnd: boolean) => void) | null; set portTargeted(value: ((node: Node | null, port: GraphObject | null, tempNode: Node, tempPort: GraphObject, toEnd: boolean) => void) | null); } /** * This enumeration specifies possible values for {@link LinkingTool.direction}. * @since 3.0 * @category Tool */ export declare enum LinkingDirection { /** * Users may draw new links in either direction. */ Either = 1, /** * Users may draw new links forwards only (i.e. from "from" node to "to" node). */ ForwardsOnly = 2, /** * Users may draw new links backwards only (i.e. from "to" node to "from" node). */ BackwardsOnly = 3 } /** * The LinkingTool lets a user draw a new {@link Link} between two ports, * using a mouse-drag operation. * * By default an instance of this tool is installed as a mouse-move tool in the * {@link Diagram.toolManager} as the {@link ToolManager.linkingTool}. * However this tool may be used modally, as described below. * * {@link canStart} calls {@link findLinkablePort} to find a valid "port" element * from which (or to which) the user may interactively draw a new link. * {@link doActivate} sets up a temporary link and two temporary nodes, * one at the start port and one following the mouse. *

* For a general discussion of validation, see Introduction to Validation. * * This tool does not utilize any {@link Adornment}s or tool handles. * * This tool conducts a transaction while the tool is active. * A successful linking will result in a "LinkDrawn" {@link DiagramEvent} and a "Linking" transaction. * * If you want to programmatically start a new user mouse-gesture to draw a new link * from a given {@link GraphObject} that either is a "port" or may be within * the visual tree of a "port", set the {@link startObject} property * to let {@link findLinkablePort} find the real "port" element. * Then start and activate this tool: * ```js * const tool = myDiagram.toolManager.linkingTool; * tool.startObject = ...; * myDiagram.currentTool = tool; * tool.doActivate(); * ``` * @category Tool */ export class LinkingTool extends LinkingBaseTool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.linkingTool}, which you can modify. * * The {@link Tool.name} of this tool is "Linking". */ constructor(init?: Partial); /** * @deprecated See {@link LinkingDirection.Either}. */ static readonly Either = LinkingDirection.Either; /** * @deprecated See {@link LinkingDirection.ForwardsOnly}. */ static readonly ForwardsOnly = LinkingDirection.ForwardsOnly; /** * @deprecated See {@link LinkingDirection.BackwardsOnly}. */ static readonly BackwardsOnly = LinkingDirection.BackwardsOnly; /** * Gets or sets a data object that is copied by {@link insertLink} * and added to the {@link GraphLinksModel} when creating a new {@link Link}. * The default value is an empty Object, which will be copied. * The value must be an Object for the linking operation to succeed. * A null value will cause {@link insertLink} to fail. * * The copied link data's {@link GraphLinksModel.linkFromKeyProperty} * and {@link GraphLinksModel.linkToKeyProperty} properties are set to * the corresponding node's data's key values. * If the ports have {@link GraphObject.portId} values that are not null, * the link data's {@link GraphLinksModel.linkFromPortIdProperty} * and {@link GraphLinksModel.linkToPortIdProperty} properties are also set. * * Setting this property does not raise any events. * This property is ignored if the {@link Diagram.model} is not a {@link GraphLinksModel}. */ get archetypeLinkData(): ObjectData | null; set archetypeLinkData(value: ObjectData | null); /** * Gets or sets an optional node data object representing a link label, that is copied by {@link insertLink} * and added to the {@link GraphLinksModel} when creating a new {@link Link}. * * The default value is null, which causes no such label node data to be added to the model * along with the new link data. * * {@link insertLink} calls {@link GraphLinksModel.addLabelKeyForLinkData} * to associate the label node data with the link data. * * Setting this property does not raise any events. * This property is ignored if the {@link Diagram.model} is not a {@link GraphLinksModel}. */ get archetypeLabelNodeData(): ObjectData | null; set archetypeLabelNodeData(value: ObjectData | null); /** * Gets or sets the direction in which new links may be drawn. * Possible values are {@link LinkingDirection} values.. * This defaults to {@link LinkingDirection.Either}. * Setting this property does not raise any events. */ get direction(): LinkingDirection; set direction(value: LinkingDirection); /** * Gets or sets the {@link GraphObject} at which {@link findLinkablePort} should start its search. * The default value is null. * Setting this property does not raise any events. * * If you want to explicitly start a new user mouse-gesture to draw a new link * from a given {@link GraphObject} that may be a "port" object or may be within * the visual tree of a "port" object, set this property to that object * to let {@link findLinkablePort} find the real "port" object. * Then start and activate this tool: * ```js * const tool = myDiagram.toolManager.linkingTool; * tool.startObject = ...; * myDiagram.currentTool = tool; * tool.doActivate(); * ``` */ get startObject(): GraphObject | null; set startObject(value: GraphObject | null); /** * This tool can run when the diagram allows linking, the model is modifiable, * the left-button mouse drag has moved far enough away to not be a click, and * when {@link findLinkablePort} has returned a valid port * or when {@link startObject} is a valid port. * * This method may be overridden, but we recommend that you call this base method. */ canStart(): boolean; /** * Return the {@link GraphObject} at the mouse-down point, * if it is part of a node and if it is valid to link with it. * * This starts looking for a port at the {@link startObject} if it is non-null, * otherwise it looks for an object at the {@link Diagram.firstInput}'s {@link InputEvent.documentPoint}. * If it finds no object, or if the object it finds is not in a node, this method returns null. * If it does find a port, it should set {@link isForwards} to declare which direction the new link is being drawn. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns If the {@link direction} is {@link LinkingDirection.Either} or {@link LinkingDirection.ForwardsOnly}, * this checks the element and its parent {@link Node} by calling {@link LinkingBaseTool.isValidFrom}. * If the {@link direction} is {@link LinkingDirection.Either} or {@link LinkingDirection.BackwardsOnly}, * this checks the element and its parent {@link Node} by calling {@link LinkingBaseTool.isValidTo}. * In either case finding a matching port will return that port and set {@link LinkingBaseTool.isForwards} appropriately. * Otherwise this will return null. */ findLinkablePort(): GraphObject | null; /** * Start the linking operation. * * This calls {@link findLinkablePort} to find the port from which to start drawing a new link. * If the {@link startObject} is already set, it uses that object to find the starting port. * If it is not set, it looks for a linkable port at the {@link Diagram.firstInput} point. * If it finds one, it remembers it as the starting port, otherwise it stops this tool. * * It then starts a transaction, captures the mouse, and changes the cursor. * Next it initializes and adds the {@link LinkingBaseTool.temporaryFromNode}, * {@link LinkingBaseTool.temporaryToNode}, and {@link LinkingBaseTool.temporaryLink} to the diagram. * The temporary nodes that are positioned and sized to be like the real {@link LinkingBaseTool.originalFromPort} * and {@link LinkingBaseTool.originalToPort} ports. * The temporary link connects the two temporary ports, of course. * * This method may be overridden, but we recommend that you call this base method. */ doActivate(): void; /** * Finishing the linking operation stops the transaction, releases the mouse, and resets the cursor. * * This method may be overridden, but we recommend that you call this base method. */ doDeactivate(): void; /** * A mouse-up ends the linking operation; if there is a valid {@link targetPort} nearby, * this adds a new {@link Link} by calling {@link insertLink}. * * If there is a new link, it is selected and the "LinkDrawn" {@link DiagramEvent} is raised * with the new link as the {@link DiagramEvent.subject}. * If there is no new link, this calls {@link doNoLink}. * In any case this stops the tool. * * This method also raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed in a "Linking" transaction, but the "ChangedSelection" event is raised outside the transaction. * * This method may be overridden, but we recommend that you call this base method. * It is usually easier to override {@link insertLink} or just set {@link archetypeLinkData}. * It is also common to implement a "LinkDrawn" {@link DiagramEvent} listener on the {@link Diagram}. */ doMouseUp(): void; /** * Make a copy of the {@link archetypeLinkData}, set its node and port properties, and add it to the {@link GraphLinksModel}. * If the model is a {@link TreeModel}, set the parent key of the child's node data object. * * For GraphLinksModels, if {@link archetypeLabelNodeData} is non-null, this method also adds that node data as an initial label node * for the new link data. * * For TreeModels, if {@link Diagram.isTreePathToChildren} is false, the roles of the *fromnode* and *tonode* arguments are exchanged. * * This method may be overridden, but we recommend that you call this base method. * Usually though it is easiest to just set {@link archetypeLinkData} to control what kind of link is created. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromnode * @param fromport - the from-port, or null to use the node itself * @param tonode * @param toport - the to-port, or null to use the node itself * @returns the newly created Link, or null if it failed. * @see {@link doNoLink} */ insertLink(fromnode: Node | null, fromport: GraphObject | null, tonode: Node | null, toport: GraphObject | null): Link | null; /** * This method is called upon a mouse up when no new link is drawn, * either because no valid {@link LinkingBaseTool.targetPort} was found or because * {@link insertLink} returned null. * * This method may be overridden. By default this method does nothing. * If you want to successfully perform any side-effects, you will need to set {@link Tool.transactionResult} to a string; * otherwise this tool's transaction will be rolled-back. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param fromnode * @param fromport - the from-port, or null to use the node itself * @param tonode * @param toport - the to-port, or null to use the node itself */ doNoLink(fromnode: Node | null, fromport: GraphObject | null, tonode: Node | null, toport: GraphObject | null): void; } /** * The RelinkingTool allows the user to reconnect an existing {@link Link} * if the {@link Link.relinkableTo} and/or {@link Link.relinkableFrom} properties are true. *

* For a general discussion of validation, see Introduction to Validation. * * By default an instance of this tool is installed as a mouse-down tool in the * {@link Diagram.toolManager} as the {@link ToolManager.relinkingTool}. * * This tool makes use of two {@link Adornment}s, * each including a relink handle (potentially one for each end of the link), * shown when a link is selected. * * This tool conducts a transaction while the tool is active. * A successful relinking will result in a "LinkRelinked" {@link DiagramEvent} and a "Relinking" transaction. * * If you want to programmatically start a new user's relinking of a {@link Link}, * you can set the {@link handle} property to the specific "RelinkFrom" or "RelinkTo" handle and * then start and activate the tool. * ```js * const tool = myDiagram.toolManager.relinkingTool; * tool.originalLink = ...; // specify which Link to have the user reconnect * tool.isForwards = true; // specify which end of the Link to reconnect * myDiagram.currentTool = tool; // starts the RelinkingTool * tool.doActivate(); // activates the RelinkingTool * ``` * @category Tool */ export class RelinkingTool extends LinkingBaseTool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.relinkingTool}, which you can modify. * * The {@link Tool.name} of this tool is "Relinking". */ constructor(init?: Partial); /** * Show an {@link Adornment} for each end of the {@link Link} that the user may reconnect. * The Adornment may have a copy of {@link fromHandleArchetype} and/or {@link toHandleArchetype}. * * This method may be overridden. * @param part */ updateAdornments(part: Part): void; /** * (undocumented) * Create and return an {@link Adornment} that lets the user grab a handle to reconnect one end of the selected link. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param selelt - the {@link GraphObject} of the {@link Link} being relinked. * @param toend */ makeAdornment(selelt: GraphObject, toend: boolean): Adornment | null; /** * Gets or sets a small GraphObject that is copied as a relinking handle for the selected link path * at the "from" end of the link. * By default this is a {@link Shape} that is a small blue diamond. * Setting this property does not raise any events. * * Here is an example of changing the default handle to be larger green triangles: * ```js * myDiagram.toolManager.relinkingTool.fromHandleArchetype = * new go.Shape('Triangle', * { width: 10, height: 10, fill: 'limegreen', segmentIndex: 0, cursor: 'pointer' }); * ``` * @see {@link toHandleArchetype} */ get fromHandleArchetype(): GraphObject | null; set fromHandleArchetype(value: GraphObject | null); /** * Gets or sets a small GraphObject that is copied as a relinking handle for the selected link path * at the "to" end of the link. * By default this is a {@link Shape} that is a small blue diamond. * Setting this property does not raise any events. * * Here is an example of changing the default handle to be larger orange triangles: * ```js * myDiagram.toolManager.relinkingTool.toHandleArchetype = * new go.Shape('Triangle', * { width: 10, height: 10, fill: 'orange', segmentIndex: -1, cursor: 'pointer' }); * ``` * @see {@link fromHandleArchetype} */ get toHandleArchetype(): GraphObject | null; set toHandleArchetype(value: GraphObject | null); /** * Returns the {@link GraphObject} that is the tool handle being dragged by the user. * This will be contained by an {@link Adornment} whose category is "RelinkFrom" or "RelinkTo". * Its {@link Adornment.adornedPart} is the same as the {@link originalLink}. * * This property is also settable, but should only be set either within an override of {@link doActivate} * or prior to calling {@link doActivate}. */ get handle(): GraphObject | null; set handle(value: GraphObject | null); /** * This tool can run when the diagram allows relinking, the model is modifiable, * and there is a relink handle at the mouse-down point. * * This method may be overridden, but we recommend that you call this base method. */ canStart(): boolean; /** * Start the relinking operation. * * Find the relink handle by calling {@link Tool.findToolHandleAt} * looking for either the "RelinkFrom" adornment or the "RelinkTo" adornment, * saving the result in {@link handle}. * * Normally when this method is called the value of {@link LinkingBaseTool.originalLink} and {@link handle} will be null, * resulting in a call to {@link Tool.findToolHandleAt} to find a "RelinkFrom" or "RelinkTo" tool handle, * which is then remembered as the value of {@link handle}. * If when this method is called the value of {@link handle} is already set, * then there is no need to call {@link Tool.findToolHandleAt}, * because the programmer has already set up which relinking handle they want the user to be relinking. * Finding a handle is not necessary if {@link LinkingBaseTool.originalLink} and * {@link isForwards} have been set before calling this method. * * This starts a transaction, captures the mouse, and sets the cursor. * * If {@link LinkingBaseTool.originalLink} or {@link handle} was not set beforehand, * the value of {@link isForwards} is set depending on the category of the relink handle found. * The {@link LinkingBaseTool.originalLink} property and various * "Original..." port and node properties are set too. * The temporary nodes and temporary link are also initialized. * * This method may be overridden, but we recommend that you call this base method. */ doActivate(): void; /** * Make a temporary link look and act like the real Link being relinked. * By default this method copies many of the routing-oriented properties * from the {@link LinkingBaseTool.originalLink} to the {@link LinkingBaseTool.temporaryLink}. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param reallink * @param templink */ protected copyLinkProperties(reallink: Link | null, templink: Link): void; /** * Finishing the linking operation stops the transaction, releases the mouse, and resets the cursor. * * This method may be overridden, but we recommend that you call this base method. */ doDeactivate(): void; /** * A mouse-up ends the relinking operation; if there is a valid {@link targetPort} nearby, * this modifies the old link to connect with the target port. * * A successful relinking calls {@link reconnectLink} to actually change the link. * The "LinkRelinked" {@link DiagramEvent} is raised with the link as the {@link DiagramEvent.subject} * and with the now-disconnected original port as the {@link DiagramEvent.parameter}. * If the link was not reconnected, this calls {@link doNoRelink}. * In any case this stops the tool. * * A failure to find a valid target port results in no changes and no DiagramEvent. * * This method may be overridden, but we recommend that you call this base method. * You might find it easier to override {@link reconnectLink}. * It is actually most common to implement a "LinkRelinked" {@link DiagramEvent} listener on the {@link Diagram}. */ doMouseUp(): void; /** * Modify an existing {@link Link} to connect to a new node and port. * * This method may be overridden, but we recommend that you call this base method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param existinglink * @param newnode - the {@link Node} to connect to or from. * @param newport - the {@link GraphObject} port to connect to or from. * @param toend - If true, this modifies the link's "to" node and port; otherwise it modifies the "from" node and port. * @returns true if successful. * @see {@link doNoRelink} */ reconnectLink(existinglink: Link, newnode: Node | null, newport: GraphObject | null, toend: boolean): boolean; /** * This method is called upon a mouse up when {@link reconnectLink} is not called. * * This method may be overridden. By default this method does nothing. * If you want to successfully perform any side-effects, you will need to set {@link Tool.transactionResult} to a string; * otherwise this tool's transaction will be rolled-back. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param existinglink * @param toend - If true, the user was trying to modify the link's "to" node and port. */ doNoRelink(existinglink: Link, toend: boolean): void; } /** * This enumeration specifies possible values for {@link LinkReshapingTool.setReshapingBehavior} and {@link LinkReshapingTool.setReshapingBehavior}. * @since 3.0 * @category Tool */ export declare enum ReshapingBehavior { /** * Disallow dragging. */ None = 0, /** * Allow only horizontal (left-and-right) dragging. */ Horizontal = 1, /** * Allow only vertical (up-and-down) dragging. */ Vertical = 2, /** * Allow dragging in any direction. */ All = 3 } /** * The LinkReshapingTool is used to interactively change the route of a {@link Link} * by setting its {@link Link.points} list. * You may want to save the route to the model by using a TwoWay {@link Binding} on the "points" property of the Link. * * This tool makes use of an {@link Adornment}, shown when the adorned {@link Link} is selected, * that includes some number of reshape handles. * This tool conducts a transaction while the tool is active. * A successful reshaping will result in a "LinkReshaped" {@link DiagramEvent} and a "LinkReshaping" transaction. * *

* For a general discussion of link routing, see: * Introduction to Links, * Introduction to Link Labels, and * Introduction to Link Connection Points. * For customizing the linking tools, see Introduction to the Linking Tools. * For a general discussion of validation, see Introduction to Validation. * @category Tool */ export class LinkReshapingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.linkReshapingTool}, which you can modify. * * The {@link Tool.name} of this tool is "LinkReshaping". */ constructor(init?: Partial); /** * @deprecated See {@link ReshapingBehavior.None}. */ static readonly None = ReshapingBehavior.None; /** * @deprecated See {@link ReshapingBehavior.Horizontal}. */ static readonly Horizontal = ReshapingBehavior.Horizontal; /** * @deprecated See {@link ReshapingBehavior.Vertical}. */ static readonly Vertical = ReshapingBehavior.Vertical; /** * @deprecated See {@link ReshapingBehavior.All}. */ static readonly All = ReshapingBehavior.All; /** * Get the permitted reshaping behavior for a particular reshape handle. * @param obj - a reshape handle in the "LinkReshaping" Adornment. * @returns a ReshapingBehavior value */ protected getReshapingBehavior(obj: GraphObject): ReshapingBehavior; /** * Set the permitted reshaping behavior for a particular reshape handle. * @param obj - a reshape handle in the "LinkReshaping" Adornment. * @param behavior - one of ReshapingBehavior.All, .Vertical, .Horizontal, or .None */ protected setReshapingBehavior(obj: GraphObject, behavior: ReshapingBehavior): void; /** * Show an {@link Adornment} with reshape handles at each of the interesting points of the link's route, * if the link is selected and visible and if {@link Part.canReshape} is true. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param part */ updateAdornments(part: Part): void; /** * (undocumented) * @virtual * @param pathshape */ makeAdornment(pathshape: GraphObject): Adornment | null; /** * (undocumented) * Create and return a {@link GraphObject} that the user can "grab" to relink the selected Link. * By default this returns a copy of {@link handleArchetype}, a {@link Shape} that is a small blue rectangle. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pathshape - the {@link GraphObject} path of the link being reshaped. * @param idx - the index of the route point to be moved. */ makeHandle(pathshape: GraphObject, idx: number): GraphObject | null; /** * Gets or sets a small GraphObject that is copied as a reshape handle at each movable point in the selected link's route. * By default this is a {@link Shape} that is a small blue rectangle. * Setting this property does not raise any events. * * Here is an example of changing the default handles to be larger yellow circles: * ```js * myDiagram.toolManager.linkReshapingTool.handleArchetype = * new go.Shape('Circle', { width: 10, height: 10, fill: 'yellow' }); * ``` * @see {@link midHandleArchetype} */ get handleArchetype(): GraphObject | null; set handleArchetype(value: GraphObject | null); /** * (undocumented) * Create and return a {@link GraphObject} that the user can "grab" to add a segment to the selected Link. * By default this returns a copy of {@link midHandleArchetype}, a {@link Shape} that is a small blue diamond. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pathshape - the {@link GraphObject} path of the link being reshaped. * @param idx - the index of the route point to be moved. */ makeResegmentHandle(pathshape: GraphObject, idx: number): GraphObject | null; /** * Gets or sets a small GraphObject that is copied as a resegment handle at each mid-point in the selected Link's route. * By default this is a {@link Shape} that is a small blue diamond. * Setting this property does not raise any events. * * Here is an example of changing the default handle to be larger cyan triangles: * ```js * myDiagram.toolManager.linkReshapingTool.midHandleArchetype = * new go.Shape('Triangle', { width: 10, height: 10, fill: 'cyan' }); * ``` * @see {@link handleArchetype} */ get midHandleArchetype(): GraphObject | null; set midHandleArchetype(value: GraphObject | null); /** * Returns the {@link GraphObject} that is the tool handle being dragged by the user. * This will be contained by an {@link Adornment} whose category is "LinkReshaping". * Its {@link Adornment.adornedPart} is the same as the {@link adornedLink}. * This is normally set by {@link doActivate}, remembering the result of the call to {@link Tool.findToolHandleAt}. */ get handle(): GraphObject | null; set handle(value: GraphObject | null); /** * This read-only property returns the {@link Link} that is being routed manually. */ get adornedLink(): Link | null; /** * This tool may run when there is a mouse-down event on a reshape handle. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Start reshaping, if {@link findToolHandleAt} finds a reshape handle at the mouse down point. * * If successful this sets {@link handle} to be the reshape handle that it finds * and {@link adornedLink} to be the {@link Link} being routed. * It also remembers the original link route (a list of Points) in case this tool is cancelled. * And it starts a transaction. */ doActivate(): void; /** * This stops the current reshaping operation with the link route shaped the way it is. */ doDeactivate(): void; /** * This calls the super {@link Tool.stopTransaction} method, and if the result is `true`, * attempts to optimize the transaction by removing all changes except the first and last * by calling {@link Transaction.optimize}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the result of the call to rollback or commit the transaction. */ stopTransaction(): boolean; /** * Restore the link route to be the original points and stop this tool. */ doCancel(): void; /** * (undocumented) * If the handle clicked during activation was a resegment handle, return the point at which to start a new segment. * By default this returns the center of the handle that was clicked. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the point where resegmenting begins */ protected getResegmentingPoint(): Point; /** * Call {@link reshape} with a new point determined by the mouse * to change the route of the {@link adornedLink}. */ doMouseMove(): void; /** * Reshape the route with a point based on the most recent mouse point by calling {@link reshape}, * and then raise a "LinkReshaped" {@link DiagramEvent} before stopping this tool. */ doMouseUp(): void; /** * Gets or sets the distance from a straight line that controls whether a * {@link Link.resegmentable} Link segment is kept as a separate segment or * removed to form a straight segment of the adjacent points. * * The default value is 3. * @since 3.0 */ get resegmentingDistance(): number; set resegmentingDistance(value: number); /** * Change the route of the {@link adornedLink} by moving the point corresponding to the current * {@link handle} to be at the given {@link Point}. * This is called by {@link doMouseMove} and {@link doMouseUp} with the result of calling * {@link computeReshape} to constrain the input point. * * This method respects the orthogonality of the link, if necessary limiting movement along only one axis. * To maintain orthogonality it may need to modify more than one point in the route. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newPoint - the value of the call to {@link computeReshape}. */ reshape(newPoint: Point): void; /** * This is called by {@link doMouseMove} and {@link doMouseUp} to limit the input point * before calling {@link reshape}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param p - the point where the handle is being dragged. * @returns Either the same Point p or one constrained by the reshape behavior to be moved * only vertically or only horizontally. */ computeReshape(p: Point): Point; /** * This read-only property returns the {@link Point} that was the original location of the handle that is being dragged to reshape the Link. */ get originalPoint(): Point; /** * This read-only property returns the {@link List} of {@link Point}s that was the original route of the Link that is being reshaped. * This List should not be modified; its value is indeterminate until a reshaping has been activated. */ get originalPoints(): List; } /** * The ResizingTool is used to interactively change the size of a {@link GraphObject} * in the selected {@link Part} or {@link Node} by setting its {@link GraphObject.desiredSize} property. * You may want to save the size to the model by using a TwoWay {@link Binding} on the "desiredSize" property * of the GraphObject that is named by {@link Part.resizeObjectName}. * This tool does not operate on {@link Link}s. * * You can limit the permitted minimum and maximum dimensions by setting * {@link minSize} and {@link maxSize}. * The resizing will also respect the {@link GraphObject.minSize} and * {@link GraphObject.maxSize} properties. * Width or height values that are NaN do not constrain the resizing. * Override {@link computeMinSize} and/or {@link computeMaxSize} to change this behavior. * * You can also limit the width and/or height to be multiples of a particular size by * setting {@link Part.resizeCellSize}. * If either or both of these values are NaN, as they are by default, * it will get the values from this tool's {@link cellSize}. * Finally it will consider the {@link Diagram.grid}'s {@link Panel.gridCellSize} * if {@link isGridSnapEnabled} is true. * Override {@link computeCellSize} to change this behavior. * * Pressing the Shift key or resizing a {@link Shape} with a {@link Shape.geometryStretch} of * {@link GeometryStretch.Uniform} will maintain the aspect ratio during the resize. * Override {@link computeReshape} to change this behavior. * * This tool makes use of an {@link Adornment}, shown when the {@link Part} or {@link Node} is selected, * that includes some number of resize handles. * The resize handles are normally copies of {@link ResizingTool.handleArchetype}, * unless you specify a custom resize Adornment by setting {@link Part.resizeAdornmentTemplate}. * The resize Adornment is normally a "Spot" Panel with eight resize handles, * each with {@link GraphObject.alignment} set to one of the eight standard {@link Spot} values -- * the four corners and the four side middles. * The {@link GraphObject.alignment} is what identifies and distinguishes each of the handles and * the behavior when the user drags the handle. * * This tool conducts a transaction while the tool is active. * A successful resizing will result in a "PartResized" {@link DiagramEvent} and a "Resizing" transaction. *

* For a general discussion of the sizing of objects, see: Introduction to the sizing of GraphObjects. * For customizing the ResizingTool, see Introduction to the ResizingTool. * * If you want to programmatically start a user's resizing of the {@link Part.resizeObject} of an existing selected node, * you can set the {@link handle} property to the specific resize handle and then start and activate the tool. * ```js * const node = ...; * myDiagram.select(node); * const adorn = node.findAdornment("Resizing"); * const tool = myDiagram.toolManager.resizingTool; * // specify which resize handle of the "Resizing" Adornment of the selected node * tool.handle = adorn.elt(...); * myDiagram.currentTool = tool; // starts the ResizingTool * tool.doActivate(); // activates the ResizingTool * ``` * @category Tool */ export class ResizingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.resizingTool}, which you can modify. * * The {@link Tool.name} of this tool is "Resizing". */ constructor(init?: Partial); /** * Show an {@link Adornment} with the resize handles at points along the edge of the bounds of the * selected {@link Part}'s {@link Part.resizeObject}. * * First this finds the object in the visual tree of the Part that should * get the resize adornment and that the user will be able to resize interactively. * It finds the object that has the {@link Part.resizeObjectName} property of the Part. * If the {@link Part.resizeObjectName} property is an empty string, as it is by default, * it uses the whole part. * * It then builds the adornment, associating it with the chosen resize object. * If {@link Part.resizeAdornmentTemplate} is non-null, it is copied. * Otherwise it constructs a new Adornment with a {@link Placeholder} and eight copies of {@link handleArchetype}, * four at the corners and four at the middle of each side. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param part */ updateAdornments(part: Part): void; /** * (undocumented) * Create and return an {@link Adornment} that lets the user grab a handle to resize the selected part. * The Adornment will be a "Spot" Panel with a {@link Placeholder} and eight copies of {@link handleArchetype}. * Each handle will have one of the standard Spots as their {@link GraphObject.alignment}. * * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param resizeObj - the {@link GraphObject} being resized. */ makeAdornment(resizeObj: GraphObject): Adornment | null; /** * (undocumented) * @virtual * @param elt * @param angle */ updateResizeHandles(elt: GraphObject, angle: number): void; /** * Gets or sets a small GraphObject that is copied as a resizing handle for the selected part. * By default this is a {@link Shape} that is a small blue rectangle. * This ResizingTool will automatically update the {@link GraphObject.cursor} property to match * the corresponding corners or sides, if it is set to "pointer" or "...resize" in this archetype. * Setting this property does not raise any events. * * Here is an example of changing the default handle to be larger yellow circles: * ```js * myDiagram.toolManager.resizingTool.handleArchetype = * new go.Shape('Circle', { width: 10, height: 10, fill: 'yellow', cursor: 'pointer' }); * ``` * * This property is ignored when a custom resizing Adornment is specified as the {@link Part.resizeAdornmentTemplate}. * That property is normally null, in which case this tool will automatically construct Adornments * holding eight copies of this handle archetype, each with a {@link GraphObject.alignment} being one of the * standard eight {@link Spot}s. */ get handleArchetype(): GraphObject | null; set handleArchetype(value: GraphObject | null); /** * Returns the {@link GraphObject} that is the tool handle being dragged by the user. * This will be contained by an {@link Adornment} whose category is "ResizingTool". * Its {@link Adornment.adornedObject} is the same as the {@link adornedObject}. * This is normally set by {@link doActivate}, remembering the result of the call to {@link Tool.findToolHandleAt}. * * This property is also settable, but should only be set either within an override of {@link doActivate} * or prior to calling {@link doActivate}. */ get handle(): GraphObject | null; set handle(value: GraphObject | null); /** * Gets or sets the {@link GraphObject} that is being resized. * This may be the same object as the selected {@link Part} or it may be contained within that Part. * * This property is also settable, but should only be set when overriding functions * in ResizingTool, and not during normal operation. */ get adornedObject(): GraphObject | null; set adornedObject(value: GraphObject | null); /** * This tool may run when there is a mouse-down event on a resize handle, * the diagram is not read-only and it allows resizing, * the left mouse button is being used, * and this tool's adornment's resize handle is at the current mouse point. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Find the {@link handle}, remember the object's original bounds, * save the results of calling {@link computeMinSize}, {@link computeMaxSize}, and {@link computeCellSize}, * capture the mouse, and start a transaction. * * Normally when this method is called the value of {@link handle} will be null, * resulting in a call to {@link Tool.findToolHandleAt} to find a "Resizing" tool handle, * which is then remembered as the value of {@link handle}. * If when this method is called the value of {@link handle} is already set, * then there is no need to call {@link Tool.findToolHandleAt}, * because the programmer has already set up which resize handle they want the user to be resizing. */ doActivate(): void; /** * Stop the current transaction, forget the {@link handle} and {@link adornedObject}, and release the mouse. */ doDeactivate(): void; /** * This calls the super {@link Tool.stopTransaction} method, and if the result is `true`, * attempts to optimize the transaction by removing all changes except the first and last * by calling {@link Transaction.optimize}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the result of the call to rollback or commit the transaction. */ stopTransaction(): boolean; /** * Restore the original size of the {@link GraphObject}. */ doCancel(): void; /** * Call {@link resize} with a new size determined by the current mouse point. * This determines the new bounds by calling {@link computeResize}. * * When this calls {@link computeResize} it passes as the reshape argument the result of calling {@link computeReshape}. * The min, max, and cell arguments will be the saved results of {@link doActivate}'s calls to {@link computeMinSize}, {@link computeMaxSize}, and {@link computeCellSize}. */ doMouseMove(): void; /** * Call {@link resize} with the final bounds based on the most recent mouse point, * commit the transaction, and raise the "PartResized" {@link DiagramEvent}. * This determines the new bounds by calling {@link computeResize}. * * When this calls {@link computeResize} it passes as the reshape argument the result of calling {@link computeReshape}. */ doMouseUp(): void; /** * Change the size of the selected part's {@link Part.resizeObject} to have the given bounds. * This modifies its {@link GraphObject.desiredSize} and maybe its {@link Part.location}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newr - a Rectangle in the {@link adornedObject}'s local coordinates, not in document coordinates */ resize(newr: Rect): void; /** * Given a {@link Spot} in the original bounds of the object being resized and a new {@link Point}, * compute the new {@link Rect}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newPoint - a Point in local coordinates. * @param spot - the alignment spot of the handle being dragged. * @param min - the result of the call to {@link computeMinSize}. * @param max - the result of the call to {@link computeMaxSize}. * @param cell - the result of the call to {@link computeCellSize}. * @param reshape - true if the new size may change the aspect ratio from that of the natural bounds of the {@link adornedObject}. * @returns a Rectangle in the {@link adornedObject}'s local coordinates, not in document coordinates */ computeResize(newPoint: Point, spot: Spot, min: Size, max: Size, cell: Size, reshape: boolean): Rect; /** * Decide whether to allow arbitrary reshaping or whether to keep the same aspect ratio of the object being resized. * If the {@link adornedObject} is a {@link Shape}, * then if the {@link Shape.geometryStretch} is {@link GeometryStretch.Uniform}, * this method will return false to restrict reshaping to maintain the object's current ratio of height to width. * Also, if the user is holding down the Shift key, this method will return false. * * This is called on each mouse-move and on mouse-up; the result is passed to the call to {@link resize}. * This permits the user to change the behavior dynamically during resizing. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * For example, to always keep the object's original aspect ratio, override this method to return false. * When initializing a {@link Diagram}: * ```js * const diagram = new go.Diagram, "myDiagramDiv" * { * "resizingTool.computeReshape": function() { return false; }, * // ... rest of Diagram init * }) * ``` * Or when overriding the method dynamically: * ```js * myDiagram.toolManager.resizingTool.computeReshape = function() { return false; } * ``` * Your override might want to look at the `this.adornedObject.part.data` properties to decide whether to allow reshaping. * @virtual * @returns true to allow any aspect ratio; false to preserve the {@link adornedObject}'s height/width ratio */ computeReshape(): boolean; /** * The effective minimum resizing size is the maximum of {@link minSize} and the * {@link adornedObject}'s {@link GraphObject.minSize}. * * This is called once when the tool is activated. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ computeMinSize(): Size; /** * The effective maximum resizing size is the minimum of the {@link maxSize} and the * {@link adornedObject}'s {@link GraphObject.maxSize}. * * This is called once when the tool is activated. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ computeMaxSize(): Size; /** * The size should be a multiple of the value returned by this method. * * This is called once when the tool is activated. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ computeCellSize(): Size; /** * Gets or sets the minimum size to which the user can resize. * The effective minimum size is the maximum of this value and the {@link GraphObject.minSize}, * independently in each direction. * * The default value is `go.Size(1, 1)`. * Any new value must be of type Size; `NaN` width or height values are treated as zero. * Setting this property does not raise any events. */ get minSize(): Size; set minSize(value: Size); /** * Gets or sets the maximum size to which the user can resize. * The effective maximum size is the minimum of this value and the {@link GraphObject.maxSize}, * independently in each direction. * * The default value is `go.Size(9999, 9999)`. * Any new value must be of type Size; `NaN` width or height values are treated as Infinity. * Setting this property does not raise any events. */ get maxSize(): Size; set maxSize(value: Size); /** * Gets or sets the width and height multiples with which the user must resize. * The effective cell size is computed by first looking at the {@link Adornment.adornedPart}'s {@link Part.resizeCellSize}. * If either or both of its width and height are `NaN`, it will use this property, `cellSize`. * If either or both of this property's width and height are `NaN`, it will * consider the {@link Diagram.grid}'s {@link Panel.gridCellSize}. * * The default value is `go.Size(NaN, NaN)`. * Setting this property does not raise any events. */ get cellSize(): Size; set cellSize(value: Size); /** * Gets or sets whether the {@link ResizingTool} snaps object sizes to the diagram's background grid during the resize. * By default this property is false. * Setting this property does not raise any events. */ get isGridSnapEnabled(): boolean; set isGridSnapEnabled(value: boolean); /** * Gets or sets whether the {@link ResizingTool} moves the member Parts of a Group that has no {@link Group.placeholder}. * By default this property is true. * Setting this property does not raise any events. * @since 2.1.26 */ get dragsMembers(): boolean; set dragsMembers(value: boolean); /** * Gets or sets the Point opposite to the chosen, dragged handle of the "Resizing" Adornment. * This property has no meaning until after {@link doActivate} has been called. * @since 2.2 */ get oppositePoint(): Point; set oppositePoint(value: Point); /** * This read-only property returns the {@link Size} that was the original value of the {@link GraphObject.desiredSize} * of the element that is being resized. */ get originalDesiredSize(): Size; /** * This read-only property returns the {@link Point} that was the original value of the {@link Part.location} * of the Part that is being resized. */ get originalLocation(): Point; } /** * The RotatingTool is used to interactively change the {@link GraphObject.angle} of a {@link GraphObject} * by setting its {@link GraphObject.angle} property. * You may want to save the angle to the model by using a TwoWay {@link Binding} on the "angle" property * of the GraphObject that is named by {@link Part.rotateObjectName}. * * This tool allows the user to rotate the {@link Part.rotateObject} of the selected {@link Part}. * The {@link Part} must be {@link Part.rotatable}, which is false by default. * Normally this works with {@link Part}s or {@link Node}s; it does not make sense for whole {@link Link}s * or {@link Link.path}s, so if you want to rotate a label on a Link, make sure to name that label * and refer to it as the {@link Part.rotateObjectName}. * * You can control the point about which the object is rotated by setting {@link Part.rotationSpot}. * The rotation spot can be computed dynamically by overriding {@link computeRotationPoint}. * The value of that method call is saved as {@link rotationPoint}. * * You can limit the permitted angles by setting {@link snapAngleMultiple} and {@link snapAngleEpsilon}. * For example, if you want to permit only angles that are multiples of 90 degrees, * set {@link snapAngleMultiple} to 90 and {@link snapAngleEpsilon} to 45. * Pressing the Shift key during rotation ignores these two properties. * * This tool makes use of an {@link Adornment} that includes a rotation handle. * It is shown when the selected {@link Part} is {@link Part.rotatable}. * You can control its direction relative to the {@link rotationPoint} * by setting {@link handleAngle} to a multiple of 90 degrees, * and its distance from the rotation point by setting {@link handleDistance}. * The rotate handle is normally a copy of {@link RotatingTool.handleArchetype}. * unless you specify a custom rotate Adornment by setting {@link Part.rotateAdornmentTemplate}. * * This tool conducts a transaction while the tool is active. * A successful rotation will result in a "PartRotated" {@link DiagramEvent} and a "Rotating" transaction. *

* For customizing the RotatingTool, see Introduction to the RotatingTool. * * If you want to programmatically start a user's rotating of the {@link Part.rotateObject} of an existing selected node, * you can set the {@link handle} property to the rotate handle and then start and activate the tool. * ```js * const node = ...; * myDiagram.select(node); * const adorn = node.findAdornment("Rotating"); * const tool = myDiagram.toolManager.rotatingTool; * // specify the rotation handle of the "Rotating" Adornment of the selected node * tool.handle = adorn.elt(0); * myDiagram.currentTool = tool; // starts the RotatingTool * tool.doActivate(); // activates the RotatingTool * ``` * @category Tool */ export class RotatingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.rotatingTool}, which you can modify. * * The {@link Tool.name} of this tool is "Rotating". */ constructor(init?: Partial); /** * Show an {@link Adornment} with a rotate handle at a point to the side of the adorned object * if the part is selected and visible and if {@link Part.canRotate}() is true. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param part - the part. */ updateAdornments(part: Part): void; /** * (undocumented) * Create and return an {@link Adornment} that lets the user grab a handle to rotate an object in the selected part. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param rotateObj - the {@link GraphObject} being rotated. */ makeAdornment(rotateObj: GraphObject): Adornment | null; /** * Gets or sets a small GraphObject that is copied as a rotation handle for the selected part. * By default this is a {@link Shape} that is a small yellow circle. * Setting this property does not raise any events. * * Here is an example of changing the default handle to be green "X": * ```js * myDiagram.toolManager.rotatingTool.handleArchetype = * new go.Shape('XLine', { * width: 8, * height: 8, * stroke: 'green', * fill: 'transparent', * cursor: 'pointer' * }); * ``` * * This property is ignored when a custom rotating Adornment is specified as the {@link Part.rotateAdornmentTemplate}. */ get handleArchetype(): GraphObject | null; set handleArchetype(value: GraphObject | null); /** * This read-only property returns the {@link GraphObject} that is the tool handle being dragged by the user. * This will be contained by an {@link Adornment} whose category is "RotatingTool". * Its {@link Adornment.adornedObject} is the same as the {@link adornedObject}. * * This property is also settable, but should only be set either within an override of {@link doActivate} * or prior to calling {@link doActivate}. */ get handle(): GraphObject | null; set handle(value: GraphObject | null); /** * Gets or sets the {@link GraphObject} that is being rotated. * This may be the same object as the selected {@link Part} or it may be contained within that Part. * * This property is also settable, but should only be set when overriding functions * in RotatingTool, and not during normal operation. */ get adornedObject(): GraphObject | null; set adornedObject(value: GraphObject | null); /** * This tool may run when there is a mouse-down event on a rotate handle, * the diagram is not read-only and it allows rotation, * the left mouse button is being used, * and this tool's adornment's rotate handle is at the current mouse point. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Capture the mouse, remember the original {@link GraphObject.angle}, * and start a transaction. * * Normally when this method is called the value of {@link handle} will be null, * resulting in a call to {@link Tool.findToolHandleAt} to find a "Rotating" tool handle, * which is then remembered as the value of {@link handle}. * If when this method is called the value of {@link handle} is already set, * then there is no need to call {@link Tool.findToolHandleAt}, * because the programmer has already set up which rotate handle they want the user to be rotating. */ doActivate(): void; /** * Compute the Point about which things should rotate. * This is called when this tool is activated and sometimes when updating the Adornment. * The value of the call is remembered as {@link rotationPoint}. * @virtual * @param obj - the {@link Part.rotateObject} */ computeRotationPoint(obj: GraphObject): Point; /** * Stop the current transaction, forget the {@link handle} and {@link adornedObject}, and release the mouse. */ doDeactivate(): void; /** * This calls the super {@link Tool.stopTransaction} method, and if the result is `true`, * attempts to optimize the transaction by removing all changes except the first and last * by calling {@link Transaction.optimize}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns the result of the call to rollback or commit the transaction. */ stopTransaction(): boolean; /** * Restore the original {@link GraphObject.angle} of the adorned object. */ doCancel(): void; /** * Call {@link rotate} with a new angle determined by the current mouse point. * This determines the new angle by calling {@link computeRotate}. */ doMouseMove(): void; /** * Call {@link rotate} with an angle based on the most recent mouse point, * commit the transaction, and raise the "PartRotated" {@link DiagramEvent}. */ doMouseUp(): void; /** * Change the angle of the selected part's {@link Part.rotateObject}. * This modifies its {@link GraphObject.angle}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newangle - in degrees. */ rotate(newangle: number): void; /** * Compute the new angle given a point. * If the Shift key is pressed, this method ignores the {@link snapAngleMultiple} and {@link snapAngleEpsilon}. * * If the angle is close (by {@link snapAngleEpsilon} degrees) * to a multiple of {@link snapAngleMultiple} degrees, * make it exactly that multiple. * * This method is called by both {@link doMouseMove} and {@link doMouseUp}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newPoint - in document coordinates. * @returns the new angle, in degrees. */ computeRotate(newPoint: Point): number; /** * Gets or sets the preferred angles for the selected object. * * The default value is 45 degrees, meaning that angles that are multiples * of 45 degrees are automatically preferred, if the actual angle is * close to that multiple. * The closeness is determined by the {@link snapAngleEpsilon} property. * A value of zero for {@link snapAngleMultiple} results in no snapping at all. * Setting this property does not raise any events. */ get snapAngleMultiple(): number; set snapAngleMultiple(value: number); /** * Gets or sets the the closeness to a desired angle at which the angle is "snapped to". * * The default value is 2 degrees, meaning that any angle within 2 degrees * of a multiple of the {@link snapAngleMultiple} automatically * snaps to that multiple. * Values are limited to half of the {@link snapAngleMultiple}; * such values restrict user selected angles only to exact multiples of * {@link snapAngleMultiple} -- no other angles between them. * Setting this property does not raise any events. */ get snapAngleEpsilon(): number; set snapAngleEpsilon(value: number); /** * This read-only property returns the angle that was the original value of the {@link GraphObject.angle} * of the GraphObject that is being rotated. * The value is invalid when this tool is not active. */ get originalAngle(): number; /** * Gets or sets the Point at which the axis of the rotation should be. * {@link doActivate} saves here the value returned by the call to {@link computeRotationPoint}. * The value is invalid when this tool is not active. * @since 2.0 */ get rotationPoint(): Point; set rotationPoint(value: Point); /** * Gets or sets the spot to locate the Adornment for the rotation handle when it does not have a Placeholder. * This assumes the Adornment's location will be at the center of the rotation handle. * * By default this is zero degrees, which locates the Adornment * so that it is placed to the right of an un-rotated object. * You can set this to a multiple of 90 degrees to position the rotation handle differently * with respect to the {@link rotationPoint}. * @since 2.0 */ get handleAngle(): number; set handleAngle(value: number); /** * Gets or sets the spot to locate the Adornment at a particular distance from the {@link adornedObject}. * This assumes the Adornment's location will be at the center of the rotation handle. * * By default this is 50, which locates the Adornment * so that it is placed to the right of an un-rotated object. * @since 2.0 */ get handleDistance(): number; set handleDistance(value: number); } /** * The ClickSelectingTool selects and deselects {@link Part}s when there is a click. * It does this by calling {@link Tool.standardMouseSelect}. * It is also responsible for handling and dispatching click events on {@link GraphObject}s * by calling {@link Tool.standardMouseClick}. * * Note that this tool avoids raising click events on objects that are in temporary layers. * This is to prevent parts such as selection adornments from interfering with clicking on selected nodes or links. * (Adornments are in the "Adornment" {@link Layer}, which {@link Layer.isTemporary}.) * However this means that if you add a {@link GraphObject.click} event handler on a GraphObject in an Adornment, * it will not be called. * You can get it to be called by setting {@link GraphObject.isActionable} to true on that object in the adornment. * * This tool is a standard mouse-up tool, the {@link ToolManager.clickSelectingTool}. * * This tool does not utilize any {@link Adornment}s or tool handles. * This tool does not modify the model or conduct any transaction. * * An example customization of this tool is shown in the Tree Map sample, * where the {@link Tool.standardMouseSelect} method is overridden to permit the user to cycle through * the chain of containing groups, changing the selection on each click to the next containing group. * * If you want to programmatically select a Part, you can set {@link Part.isSelected} or call {@link Diagram.select}. * If you want to know which Part is at a particular point, you can call {@link Diagram.findPartAt}. * @category Tool */ export class ClickSelectingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.clickSelectingTool}. * * The {@link Tool.name} of this tool is "ClickSelecting". */ constructor(init?: Partial); /** * This tool can run whenever a click occurs. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Upon a click, this calls {@link Tool.standardMouseSelect} to change the {@link Diagram.selection} collection, * then calls {@link Tool.standardMouseClick} to perform the normal click behaviors, * and then stops this tool. */ doMouseUp(): void; } /** * The ActionTool is responsible for handling and dispatching mouse events on {@link GraphObject}s * that have {@link GraphObject.isActionable} set to true. * This is how one implements "controls", such as buttons or sliders or knobs, as {@link GraphObject}s * that can be inside {@link Part}s without interfering with the standard tool behaviors. * * This tool allows individual GraphObjects (usually Panels) to handle mouse-down-move-up events without * having to define new {@link Tool}s. * It does this by calling {@link GraphObject.actionDown}, {@link GraphObject.actionMove}, {@link GraphObject.actionUp}, * and {@link GraphObject.actionCancel} on objects that have {@link GraphObject.isActionable} set to true. * * This tool is a standard mouse-down tool, the {@link ToolManager.actionTool}. * * This tool does not utilize any {@link Adornment}s or tool handles. * This tool does not modify the model or conduct any transaction, although the actions that this invokes may do so. * * It would be very unusual to want to customize this tool. * @category Tool */ export class ActionTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.actionTool}. * * The {@link Tool.name} of this tool is "Action". */ constructor(init?: Partial); /** * This tool can run when there is a mouse-down on an object with {@link GraphObject.isActionable} true * or if the object is within a {@link Panel} that "isActionable". * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * If there is a {@link GraphObject} found with {@link GraphObject.isActionable} set to true, * call that object's {@link GraphObject.actionDown} event, if it exists. */ doMouseDown(): void; /** * If this tool is active call {@link GraphObject.actionMove}, if it exists, on the active object. */ doMouseMove(): void; /** * Calls the {@link GraphObject.actionUp} event if defined, then effectively calls * {@link Tool.standardMouseClick} to perform the normal click behaviors, * and then stops this tool. */ doMouseUp(): void; /** * Call the {@link GraphObject.actionCancel} event if defined on the current object. */ doCancel(): void; } /** * The ClickCreatingTool lets the user create a node by clicking where they want the new node to be. * By default a double-click is required to start this tool; * set {@link isDoubleClick} to false if you want a single-click to create a node. * * This tool is a standard mouse-up tool, the {@link ToolManager.clickCreatingTool}. * However, it will not be able to start running unless you have set the * {@link archetypeNodeData} property to an object that can be copied and added to the diagram's model. * * If you set {@link isGridSnapEnabled} to true, newly created parts will be snapped to points on a grid. * * This tool does not utilize any {@link Adornment}s or tool handles. * This tool does conduct a transaction when inserting the new node. * * If you want to programmatically create a Part, you can call {@link insertPart}. * @category Tool */ export class ClickCreatingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.clickCreatingTool}, which you can modify. * * The {@link Tool.name} of this tool is "ClickCreating". */ constructor(init?: Partial); /** * This tool can run when the diagram is not read-only and supports creating new nodes, * and when there has been a click (or double-click if {@link isDoubleClick} is true) * in the background of the diagram (not on a {@link Part}), * and {@link archetypeNodeData} is an object that can be copied and added to the model. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Upon a click, call {@link insertPart} and stop this tool. */ doMouseUp(): void; /** * Create a node by adding a copy of the {@link archetypeNodeData} object * to the diagram's model, assign its {@link Part.location} * to be the given point, and select the new part. * * This starts and commits a transaction and also raises the "PartCreated" {@link DiagramEvent}. * The actual part that is added to the diagram may be a {@link Part}, a {@link Node}, * or even a {@link Group}, depending on the properties of the {@link archetypeNodeData} * and the type of the template that is copied to create the part. * * This method also raises the "ChangingSelection" and "ChangedSelection" diagram events outside the transaction. * * This method may be overridden, although it is usually much easier to just set {@link archetypeNodeData}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param loc - a Point in document coordinates. * @returns the newly created Part, or null if it failed. */ insertPart(loc: Point): Part | null; /** * Gets or sets a data object that will be copied and added to the diagram's model each time this tool executes. * The default value is null. * The value must be non-null for this tool to be able to run. * Setting this property does not raise any events. */ get archetypeNodeData(): ObjectData | null; set archetypeNodeData(value: ObjectData | null); /** * Gets or sets whether a double click rather than a single-click is required * to insert a new {@link Part} at the mouse-up point. * The default value is true -- only a double-click will cause a node to be created. * Setting this property does not raise any events. */ get isDoubleClick(): boolean; set isDoubleClick(value: boolean); /** * Gets or sets whether the {@link ClickCreatingTool} snaps object sizes to the diagram's background grid during creation. * By default this property is false. * Setting this property does not raise any events. * * @since 2.0 */ get isGridSnapEnabled(): boolean; set isGridSnapEnabled(value: boolean); } /** * The DragSelectingTool lets the user select multiple parts within a rectangular area drawn by the user. * There is a temporary part, the {@link box}, * that shows the current area encompassed between the mouse-down * point and the current mouse point. * The default drag selection box is a magenta rectangle. * You can change the {@link box} to customize its appearance -- see its documentation for an example. * * This tool is a standard mouse-move tool, the {@link ToolManager.dragSelectingTool}. * However this cannot start running unless there has been a motionless delay * after the mouse-down event of at least {@link delay} milliseconds. * * This tool does not utilize any {@link Adornment}s or tool handles, * but it does temporarily add the {@link box} part to the diagram. * This tool does not modify the model or conduct any transaction. * * Selection occurs on a mouse-up when it calls {@link selectInRect} * with the value of {@link computeBoxBounds}. * Selectable parts are selected when their bounds fall entirely within the rectangle, * unless {@link isPartialInclusion} is set to true. *

* For customizing the DragSelectingTool, see Introduction to the DragSelectingTool. * * If you implement your own drag-in-the-background-to-do-something tool, you may need to disable * this tool or insert your new tool in the {@link ToolManager.mouseMoveTools} list before this tool, * in order for your tool to run. There are examples of such tools defined in the extensions directory: * Realtime Drag Selecting Tool, * Drag Creating Tool, and * Drag Zooming Tool. * * If you want to programmatically select some Parts in a rectangular area, * you can call {@link selectInRect}. * @category Tool */ export class DragSelectingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.dragSelectingTool}, which you can modify. * * The {@link Tool.name} of this tool is "DragSelecting". */ constructor(init?: Partial); /** * This tool can run when the diagram allows selection, * there has been delay of at least {@link delay} milliseconds * after the mouse-down before a mouse-move, * there has been a mouse-drag far enough away not to be a click, * and there is no selectable part at the mouse-down point. * * The delay required to start this tool enables both this tool and * the {@link ToolManager.panningTool} to co-exist as mode-less mouse-move tools. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Capture the mouse and show the {@link box}. */ doActivate(): void; /** * Release the mouse and remove any {@link box}. */ doDeactivate(): void; /** * Update the {@link box}'s position and size according to the value * of {@link computeBoxBounds}. */ doMouseMove(): void; /** * Call {@link selectInRect} with the value of a call to {@link computeBoxBounds}. * * This method changes the cursor to "wait" and * raises the "ChangingSelection" {@link DiagramEvent} before calling {@link selectInRect}, * and raises the "ChangedSelection" DiagramEvent afterward. */ doMouseUp(): void; /** * This just returns a {@link Rect} stretching from the mouse-down point to the current mouse point. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns a {@link Rect} in document coordinates. */ computeBoxBounds(): Rect; /** * This method is called to select some parts within the area of a given rectangle. * * The normal behavior is to set the diagram's selection collection to only those parts * in the given rectangle according to the {@link isPartialInclusion} policy. * However, if the Shift key modifier is used, no parts are deselected -- * this adds to the selection the parts in the rectangle not already selected. * If the Control key (Command on Mac) modifier is used, this toggles the selectedness of the parts in the rectangle. * If the Control key (Command on Mac) and Shift key modifiers are both used, this deselects the parts in the rectangle. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param r - a rectangular bounds in document coordinates. */ selectInRect(r: Rect): void; /** * Gets or sets the time in milliseconds for which the mouse must be stationary * before this tool can be started. * The default value is 175 milliseconds. * Setting this property does not raise any events. */ get delay(): number; set delay(value: number); /** * Gets or sets whether a selectable {@link Part} may be only partly * or must be completely enclosed by the rectangle given to {@link selectInRect}. * The default value is false: parts must be completely inside the rectangle. * Setting this property does not raise any events. */ get isPartialInclusion(): boolean; set isPartialInclusion(value: boolean); /** * Gets or sets the {@link Part} used as the "rubber-band selection box" * that is stretched to follow the mouse, as feedback for what area will * be passed to {@link selectInRect} upon a mouse-up. * * Initially this is a {@link Part} containing only a simple magenta rectangular {@link Shape}. * The object to be resized during dragging should be named "SHAPE". * Setting this property does not raise any events. * * Here is an example of changing the selection box to be a thicker bright green rectangle: * ```js * myDiagram.toolManager.dragSelectingTool.box = * new go.Part({ layerName: "Tool", selectable: false }) * .add( * new go.Shape({ * name: "SHAPE", * fill: null, * stroke: "chartreuse", * strokeWidth: 3 * }) * ); * ``` * Note that the Part should be put into a {@link Layer} that {@link Layer.isTemporary}. * * Modifying this property while this tool {@link Tool.isActive} might have no effect. */ get box(): Part | null; set box(value: Part | null); } /** * The PanningTool supports manual panning, where the user can shift the * {@link Diagram.position} by dragging the mouse. * * This tool is a standard mouse-move tool, the {@link ToolManager.panningTool}. * Although the {@link ToolManager.dragSelectingTool} takes precedence over this tool, * the {@link DragSelectingTool} only starts if there is a delay after a mouse-down event. * If it does not start, then this PanningTool gets a chance to start. * * This tool does not utilize any {@link Adornment}s or tool handles. * This tool does not modify the model or conduct any transaction. * * If you want to programmatically "pan" the diagram, you can just set {@link Diagram.position} * or call methods such as {@link Diagram.scroll}, {@link Diagram.scrollToRect}, or {@link Diagram.centerRect}. * @category Tool */ export class PanningTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.panningTool}. * * The {@link Tool.name} of this tool is "Panning". */ constructor(init?: Partial); /** * This tool can run when the diagram allows scrolling and * the mouse has been dragged with the left button far enough away * from the mouse-down point to avoid being a click. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Capture the mouse, change the diagram cursor to "move", and remember the {@link Diagram.position}. */ doActivate(): void; /** * Release the mouse and restore the default diagram cursor. */ doDeactivate(): void; /** * Restore the {@link Diagram.position} to what it was when this tool activated. */ doCancel(): void; /** * Modify the {@link Diagram.position} according to how much the mouse has moved. */ doMouseMove(): void; /** * Modify the {@link Diagram.position} according to how much the mouse has moved. */ doMouseUp(): void; /** * Gets or sets whether panning actions will allow * events to bubble **instead** of panning in the diagram. * * Set this to true to allow mobile devices to scroll the page with panning gestures on the diagram. * Otherwise, the panning events will be captured and used to pan inside of the diagram. * * The default value is false. */ get bubbles(): boolean; set bubbles(value: boolean); /** * This read-only property returns the {@link Point} that was the original value of {@link Diagram.position} when the panning operation started. */ get originalPosition(): Point; } /** * HTMLInfo is used to show and hide custom HTML page elements, such as a context menu, tooltip, or text editor made of HTML. * * Properties that can be set to an HTMLInfo include: * - {@link TextEditingTool.defaultTextEditor} * - {@link TextBlock.textEditor} * - {@link GraphObject.contextMenu} * - {@link Diagram.contextMenu} * - {@link GraphObject.toolTip} * - {@link Diagram.toolTip} * * When a context menu is set to an instance of HTMLInfo, * {@link ContextMenuTool.showContextMenu} and {@link ContextMenuTool.hideContextMenu} * call {@link show} and {@link hide} respectively. You may define {@link mainElement} * instead of {@link hide} in order to automatically use a default hide method. * * When a tooltip is set to an instance of HTMLInfo, * {@link ToolManager.showToolTip} and {@link ToolManager.hideToolTip} * call {@link show} and {@link hide} respectively. * * When a text editor is set to an instance of HTMLInfo, * {@link TextEditingTool.doActivate} calls {@link show} and {@link TextEditingTool.doDeactivate} calls {@link hide}. * * For HTMLInfo to work, you must define {@link show} * and either {@link hide} or {@link mainElement}. * Typical usage will also stop the {@link ContextMenuTool} once the desired context action occurs, * typically by calling `diagram.currentTool.stopTool();`. * * Example usage of HTMLInfo can be found in the * Custom Context Menu and * HTML LightBox Context Menu samples, the * Custom TextEditingTool sample, and the * Text Editor implementation extension. * * Here is the outline for typical usage of HTMLInfo as a context menu: * ```js * // Assign an HTMLInfo to the Diagram: * myDiagram.contextMenu = new go.HTMLInfo({ * show: showContextMenu, * hide: hideContextMenu * }); * * function showContextMenu(obj, diagram, tool) { * // Show the context menu HTML element: * SomeDOMElement.style.display = "block"; * * // Also show relevant buttons given the current state * // and the GraphObject obj; if null, the context menu is for the whole Diagram * } * * function hideContextMenu() { * SomeDOMElement.style.display = "none"; * } * * function buttonClick() { * // do some action when a context menu button is clicked * * // then: * myDiagram.currentTool.stopTool(); * } * ``` * * By default, {@link TextEditingTool.defaultTextEditor} is an instance of HTMLInfo. * You can see its default implementation details here. * @category Tool */ export class HTMLInfo { /** * A newly constructed HTMLInfo can be assigned as a value of {@link TextEditingTool.defaultTextEditor}, {@link TextBlock.textEditor} * {@link GraphObject.contextMenu}, {@link Diagram.contextMenu}, {@link GraphObject.toolTip}, or {@link Diagram.toolTip}. */ constructor(init?: Partial); /** * Gets or sets the primary HTML Element that represents this HTMLInfo. * In a context menu, this would be the outermost HTML element, the one which typically * shows and hides. If this is set and {@link hide} is not, HTMLInfo will automatically execute: * ```js * info.mainElement.style.display = "none"; * ``` * * when {@link hide} would typically be called. * * This is set only for convenience; the default value for this property is null. * @see {@link hide} */ get mainElement(): HTMLElement | null; set mainElement(value: HTMLElement | null); /** * Gets or sets the function to call when an HTMLInfo is to be shown, * such as when used as the {@link GraphObject.contextMenu} or {@link Diagram.toolTip} or {@link TextBlock.textEditor}. * * If this is called by: * - {@link ContextMenuTool.showContextMenu}, the first argument is the {@link GraphObject} for which the context menu is being shown, or null for the diagram background. * - {@link ToolManager.showToolTip}, the first argument is the {@link GraphObject} for which the tooltip is being shown, or null for the diagram background. * - {@link TextEditingTool.doActivate}, the first argument is the {@link TextBlock} for which the text editor is being shown. * * If you need access to any bound data for the first argument, if it is non-null, you can get it via: * `obj.part.data` * and then you can look at any of the properties you have put on that data. * * When used as a context menu, typically shown elements, such as buttons, should call * `diagram.currentTool.stopTool();` when their action is completed. */ get show(): ((a: GraphObject, b: Diagram, c: Tool) => void) | null; set show(value: ((a: GraphObject, b: Diagram, c: Tool) => void) | null); /** * Gets or sets the function to call when an HTMLInfo is to be hidden. * The function should "hide" the HTMLInfo, either by removing any traces of it or otherwise * returning the page state to one where the HTMLInfo content is no longer considered active. * * Setting this is not strictly necessary, if no action is to be taken when hiding the HTMLInfo. * * If this is called by: * - {@link ContextMenuTool.hideContextMenu}, the second argument is the {@link ContextMenuTool}. * - {@link ToolManager.hideToolTip}, the second argument is the {@link ToolManager}. * - {@link TextEditingTool.doDeactivate}, the second argument is the {@link TextEditingTool}. * * @see {@link mainElement} */ get hide(): ((a: Diagram, b: Tool) => void) | null; set hide(value: ((a: Diagram, b: Tool) => void) | null); /** * Gets or sets a function that returns the primary value associated with this HTMLInfo, * such as the string value of a text editor, which would be solicited by the {@link TextEditingTool}. * * This typically returns a string. */ get valueFunction(): (() => any) | null; set valueFunction(value: (() => any) | null); } /** * The ContextMenuTool is used to create and show a context menu. * It automatically disables any browser context menu. * * Define context menus on individual {@link GraphObject}s by setting {@link GraphObject.contextMenu}. * Define a context menu for the diagram background by setting {@link Diagram.contextMenu}. * * This tool is a standard mouse-down tool, the {@link ToolManager.contextMenuTool}. * * This tool does not utilize any tool handles. * This tool does not modify the model or conduct any transaction, * although any code invoked by context menu commands might do so. * * There are examples of customizing this tool in the * Custom Context Menu and * HTML LightBox Context Menu samples. * * If you want to programmatically show a context menu for a particular GraphObject or for the * whole diagram, call {@link CommandHandler.showContextMenu}. * That command method is also invoked by the Menu key on the keyboard. * * Normally this shows a context menu (if available) on a right-mouse-up event. * If you want it to happen on a right-mouse-down event, you'll need to move this tool * from the {@link ToolManager.mouseUpTools} list to the {@link ToolManager.mouseDownTools} list: * ```js * myDiagram.toolManager.mouseDownTools.add(myDiagram.toolManager.replaceTool("ContextMenu", null)); * ``` * @category Tool */ export class ContextMenuTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.contextMenuTool}, which you can modify. * * The {@link Tool.name} of this tool is "ContextMenu". */ constructor(init?: Partial); /** * Return true if it's a single mouse right click that hasn't moved {@link Tool.isBeyondDragSize} * and that is on a {@link GraphObject} with a {@link GraphObject.contextMenu}. * This is also true if the mouse right click is in the diagram background * and the diagram's {@link Diagram.contextMenu} is non-null. * * On touch devices, a special default context menu will appear even if no object with a context menu is found. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * Find a {@link GraphObject} at the current mouse point with a {@link GraphObject.contextMenu}, * or return the {@link Diagram} if there is a {@link Diagram.contextMenu}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param obj - Optional GraphObject with which to start searching for a context menu. * If null, the Diagram will be used. If no argument is specified, this method will look for an object at the current mouse point. * @returns something with a `contextMenu`, * or null if nothing can be found with a context menu at the current mouse point. */ findObjectWithContextMenu(obj?: GraphObject | Diagram | null): GraphObject | Diagram | null; /** * Do nothing, activation is special and relies on doMouseUp */ doActivate(): void; /** * Activate this but also execute the normal behavior that would happen on a mouse-up * if this tool is in the {@link ToolManager.mouseDownTools} list. * Perform {@link ActionTool.doMouseDown} if a ContextMenuButton was hit. */ doMouseDown(): void; /** * If there is something found by {@link findObjectWithContextMenu}, * call {@link showContextMenu} with that object's {@link GraphObject.contextMenu} * or the {@link Diagram.contextMenu}. * * Once a context menu is being shown, * if a click occurs on a part of the context menu, call {@link Tool.standardMouseClick}. * Otherwise if the click occurs elsewhere, just stop this tool. * Unlike most tools, the first mouse-up should not stop this tool. */ doMouseUp(): void; /** * Consider calling {@link Tool.stopTool}. * @virtual * @param currobj */ maybeStopTool(currobj: GraphObject | null): void; /** * Handle mouse-enter, mouse-over, and mouse-leave events, as well as tooltips. */ doMouseMove(): void; /** * Show an {@link Adornment} or {@link HTMLInfo} as a context menu. * * This method is called by the context click ({@link Tool.doMouseDown}) and {@link CommandHandler.showContextMenu}. * If you want to programmatically show a context menu for a particular GraphObject or for the * whole diagram, do not call this method, which only does one small piece of the process of * bringing up a context menu. * Instead call {@link CommandHandler.showContextMenu}, which will start this tool * and eventually call this method and handle additional input events. * * For {@link Adornment} context menus: If the object's containing {@link Part} is data-bound, * this sets the contextmenu's `Part.data` to the same value. * The {@link Adornment.adornedObject} property is set to the {@link GraphObject} for which the menu is being shown. * * This method sets the {@link currentContextMenu}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param contextmenu * @param obj - the {@link GraphObject} for which the context menu is being shown; * this is null if the contextmenu is being shown for the diagram background. */ showContextMenu(contextmenu: Adornment | HTMLInfo, obj: GraphObject | null): void; /** * This is called by {@link showContextMenu} to position the context menu within the viewport. * It normally goes just below the cursor. * But if the mouse is too close to the right edge or the bottom edge of the viewport, * it is positioned left and/or above the cursor. * * This method only operates if the context menu, an {@link Adornment}, does not have a {@link Adornment.placeholder}. * When there is a {@link Placeholder} in the context menu, that Adornment is automatically positioned * so that the Placeholder is positioned at the adorned object, the second argument to this method. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * If you override this method to position the context menu, * the context menu has already been measured but not arranged, * so you can use its {@link GraphObject.measuredBounds} width and height * but not its {@link GraphObject.actualBounds}. * @virtual * @param contextmenu * @param obj - The {@link GraphObject} getting the context menu, * or null if the context menu is for the diagram background. */ positionContextMenu(contextmenu: Adornment, obj: GraphObject | null): void; /** * Hide any context menu. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ hideContextMenu(): void; /** * This is the {@link HTMLInfo.show} method for the {@link defaultTouchContextMenu}. * * If the object's containing {@link Part} is data-bound, * set the contextmenu's `Part.data` to the same value. * The {@link Adornment.adornedObject} property is set to the {@link GraphObject} * for which the menu is being shown. * * The menu carries some default CSS styling and uses the following CSS classes: * * * `goCXforeground` for the DIV containing the buttons * * `goCXbackground` for the darker DIV behind the context menu * * `goCXul` for the HTML `ul` items * * `goCXli` for the HTML `li` tag items * * `goCXa` for the HTML `a` tag items * * This method may be overridden. * Please read the Introduction page on Extensions * for how to override methods and how to call this base method. * @virtual */ showDefaultContextMenu(): void; /** * This is the {@link HTMLInfo.hide} method for the {@link defaultTouchContextMenu}. * * This method may be overridden. * Please read the Introduction page on Extensions * for how to override methods and how to call this base method. * @virtual */ hideDefaultContextMenu(): void; /** * Gets or sets the currently showing context menu, or null if there is none. * This is typically only set in {@link showContextMenu} and not by the user. * It is also typically set to null in {@link hideContextMenu}. */ get currentContextMenu(): Adornment | HTMLInfo | null; set currentContextMenu(value: Adornment | HTMLInfo | null); /** * Gets or sets the HTMLInfo or Adornment that acts as the default touch context menu. * On touch devices, this context menu will appear even there is no context menu defined. * * You can disable this functionality by setting this property to null. * * By default shows a set of HTML elements acting as a context menu. */ get defaultTouchContextMenu(): Adornment | HTMLInfo | null; set defaultTouchContextMenu(value: Adornment | HTMLInfo | null); /** * Gets or sets the {@link GraphObject} found at the mouse point that has a context menu. * This property remembers the result returned by {@link findObjectWithContextMenu} if it is a GraphObject. * This value is passed to {@link showContextMenu} as the second argument. * The value will be null if the context menu is for the diagram rather than for a particular GraphObject. */ get currentObject(): GraphObject | null; set currentObject(value: GraphObject | null); /** * This read-only property returns the original mouse-down point in document coordinates. */ get mouseDownPoint(): Point; } /** * This enumeration specifies possible values for {@link TextEditingTool.acceptText}. * @since 3.0 * @category Tool */ export declare enum TextEditingAccept { /** * The text editing control has lost focus. */ LostFocus = 1, /** * The user has clicked somewhere else in the diagram. */ MouseDown = 2, /** * The user has typed TAB. */ Tab = 3, /** * The user has typed ENTER. */ Enter = 4 } /** * This enumeration specifies possible values for {@link TextEditingTool.starting}. * @since 3.0 * @category Tool */ export declare enum TextEditingStarting { /** * A single click on a {@link TextBlock} with {@link TextBlock.editable} property set to true * will start in-place editing. */ SingleClick = 1, /** * A single click on a {@link TextBlock} with {@link TextBlock.editable} property set to true * will start in-place editing, but only if the {@link Part} that the {@link TextBlock} is in is already selected. */ SingleClickSelected = 2, /** * A double click on a {@link TextBlock} with {@link TextBlock.editable} property set to true * will start in-place editing. */ DoubleClick = 3 } /** * This enumeration specifies possible values for {@link TextEditingTool.state}. * @since 3.0 * @category Tool */ export declare enum TextEditingState { /** * This is the starting value before the tool is activated. */ None = 1, /** * {@link TextEditingTool.doActivate} sets the value of {@link TextEditingTool.state} to this. */ Active = 2, /** * The default text editor receiving focus sets the value of {@link TextEditingTool.state} to this. */ Editing = 3, /** * {@link TextEditingTool.acceptText} sets the value of {@link TextEditingTool.state} to this. */ Validating = 4, /** * If validation fails, {@link TextEditingTool.acceptText} sets the value of {@link TextEditingTool.state} to this. */ Invalid = 5, /** * Once accepted and the tool begins the "TextEditing" transaction, the value of {@link TextEditingTool.state} is set to this. */ Validated = 6 } /** * The TextEditingTool is used to let the user interactively edit text in place. * This sets the {@link TextBlock.text} property; you may want to save the changed text to the model * by using a TwoWay {@link Binding} on the "text" property of editable TextBlocks. * * Typically this is used by setting the {@link TextBlock.editable} property to true * on a particular {@link TextBlock} in a part. * When the part is selected and the user clicks on the {@link TextBlock} * or invokes the {@link CommandHandler.editTextBlock} command, * this tool is started and it uses an HTMLTextArea to perform in-place text editing. * (For more details see the description for {@link TextEditingTool.doActivate}.) * * The {@link TextBlock} is accessible as the {@link TextEditingTool.textBlock} property. * The text editor is accessible as the {@link TextEditingTool.currentTextEditor} property. * From the text editor control one can access the {@link TextBlock} being edited via the * 'textEditingTool' property to get to this tool, from which one can use * the {@link TextEditingTool.textBlock} property. * * You can disable mouse clicking from starting this text editing tool * by setting {@link Tool.isEnabled} to false. * You can disable the F2 key from starting this text editing tool * by making sure {@link Part.canEdit} returns false, * by either setting {@link Diagram.allowTextEdit} to false * or by setting {@link Part.textEditable} to false. * * If you want to programmatically start the user editing a particular TextBlock, * call {@link CommandHandler.editTextBlock}. * That command method is also invoked by the F2 key on the keyboard. *

* For a general discussion of text editing validation, see: Introduction to Text Validation. * For customizing the TextEditingTool, read about {@link HTMLInfo} and see Introduction to Text Editors. * @category Tool */ export class TextEditingTool extends Tool { /** * You do not normally need to create an instance of this tool * because one already exists as the {@link ToolManager.textEditingTool}, which you can modify. * * The {@link Tool.name} of this tool is "TextEditing". */ constructor(init?: Partial); /** * @deprecated See {@link TextEditingAccept.LostFocus}. */ static readonly LostFocus = TextEditingAccept.LostFocus; /** * @deprecated See {@link TextEditingAccept.MouseDown}. */ static readonly MouseDown = TextEditingAccept.MouseDown; /** * @deprecated See {@link TextEditingAccept.Tab}. */ static readonly Tab = TextEditingAccept.Tab; /** * @deprecated See {@link TextEditingAccept.Enter}. */ static readonly Enter = TextEditingAccept.Enter; /** * @deprecated See {@link TextEditingStarting.SingleClick}. */ static readonly SingleClick = TextEditingStarting.SingleClick; /** * @deprecated See {@link TextEditingStarting.SingleClickSelected}. */ static readonly SingleClickSelected = TextEditingStarting.SingleClickSelected; /** * @deprecated See {@link TextEditingStarting.DoubleClick}. */ static readonly DoubleClick = TextEditingStarting.DoubleClick; /** * @deprecated See {@link TextEditingState.None}. */ static readonly StateNone = TextEditingState.None; /** * @deprecated See {@link TextEditingState.Active}. */ static readonly StateActive = TextEditingState.Active; /** * @deprecated See {@link TextEditingState.Editing}. */ static readonly StateEditing = TextEditingState.Editing; /** * @deprecated See {@link TextEditingState.Validating}. */ static readonly StateValidating = TextEditingState.Validating; /** * @deprecated See {@link TextEditingState.Invalid}. */ static readonly StateInvalid = TextEditingState.Invalid; /** * @deprecated See {@link TextEditingState.Validated}. */ static readonly StateValidated = TextEditingState.Validated; /** * Gets or sets the {@link TextBlock} that is being edited. * This property is initially null and is set in {@link TextEditingTool.doActivate} * as the {@link TextBlock} at the mouse click point. * However, if you set this property beforehand, {@link TextEditingTool.doActivate} * will not set it, and this tool will edit the given {@link TextBlock}. */ get textBlock(): TextBlock | null; set textBlock(value: TextBlock | null); /** * Gets or sets the {@link HTMLInfo} that is editing the text. */ get currentTextEditor(): HTMLInfo | null; set currentTextEditor(value: HTMLInfo | null); /** * Gets or sets the default {@link HTMLInfo} that edits the text. * * When {@link TextEditingTool.doActivate} is called, the {@link currentTextEditor} is set to this value by default. * If a {@link TextBlock.textEditor} is specified on the TextBlock, that editor is used instead. * * This tool will call {@link HTMLInfo.show} during {@link doActivate}, * and {@link HTMLInfo.hide} during {@link doDeactivate}. * * By default the value is an {@link HTMLInfo}, and the {@link HTMLInfo.mainElement} is an `HTMLTextArea`. * You can see the default implementation details here. * * For typical operation, HTMLInfo implementations should have a way of calling {@link TextEditingTool.acceptText}. */ get defaultTextEditor(): HTMLInfo; set defaultTextEditor(value: HTMLInfo); /** * Gets or sets how user gestures can start in-place editing of text. * * Possible values are {@link TextEditingStarting} values. * * The default is {@link TextEditingStarting.SingleClickSelected} */ get starting(): TextEditingStarting; set starting(value: TextEditingStarting); /** * This may run when there is a mouse-click on a {@link TextBlock} for which the * {@link TextBlock.editable} property is true in a {@link Part} * that {@link Part.isSelected}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ canStart(): boolean; /** * This calls {@link TextEditingTool.doActivate} if there is a * {@link textBlock} set. {@link doActivate} attempts to set {@link textBlock} if it is null. */ doStart(): void; /** * Start editing the text for a {@link textBlock}. * * If {@link TextEditingTool.textBlock} is not already specified, this looks for one at the current * mouse point. If none is found, this method does nothing. * * This method sets {@link currentTextEditor}. * If {@link TextBlock.textEditor} is defined on the {@link TextBlock} it will use that as the value. * By default, it uses the value of {@link defaultTextEditor}, which is an {@link HTMLInfo} * showing an HTML textarea, with the CSS class `goTXarea`. * * If the {@link currentTextEditor} is an {@link HTMLInfo}, this method calls {@link HTMLInfo.show} on that instance. * * This sets {@link Tool.isActive} to true. * Custom text editors should call {@link TextEditingTool.acceptText} to finish the edit * by modifying the {@link TextBlock} and committing the edit transaction. * Or call {@link TextEditingTool.doCancel} to abort the edit. */ doActivate(): void; /** * Abort any text editing operation. */ doCancel(): void; /** * A click (mouse up) calls {@link TextEditingTool.doActivate} if this tool is not already active * and if {@link TextEditingTool.canStart} returns true. */ doMouseUp(): void; /** * This calls {@link acceptText} with the reason {@link TextEditingAccept.MouseDown}, * if this tool {@link Tool.isActive}. */ doMouseDown(): void; /** * Finish editing by trying to accept the new text. * * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param reason - The reason must be a {@link TextEditingAccept} value. */ acceptText(reason: TextEditingAccept): void; /** * Call the {@link textBlock}'s {@link TextBlock.errorFunction}, if there is one, * and then show the text editor again. * This is called only when the {@link isValidText} method returned false. * The value of {@link state} will be StateInvalid. * This method may be overridden. * You may wish to override this method in order to not continue showing the editor. * @virtual * @param oldstring * @param newstring * @since 2.1 */ doError(oldstring: string, newstring: string): void; /** * Call the {@link textBlock}'s {@link TextBlock.textEdited} event handler, if there is one. * This is called just after the {@link TextBlock.text} has been set to the new string value. * When this method returns, this tool raises the "TextEdited" {@link DiagramEvent} * and commits the transaction. * This method may be overridden. * @virtual * @param oldstring * @param newstring * @since 2.1 */ doSuccess(oldstring: string, newstring: string): void; /** * Release the mouse. * * If the {@link currentTextEditor} is an {@link HTMLInfo}, this calls {@link HTMLInfo.hide}. */ doDeactivate(): void; /** * This predicate checks any {@link TextBlock.textValidation} predicate and * this tool's {@link textValidation} predicate to make sure the {@link TextBlock.text} * property may be set to the new string. * * This method may be overridden, although usually it is sufficient to set {@link textValidation}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param textblock - the {@link TextBlock} that is being edited. * @param oldstr - the previous string value. * @param newstr - the proposed new string value. * @returns true if the new string is valid for the given TextBlock. */ isValidText(textblock: TextBlock, oldstr: string, newstr: string): boolean; /** * Gets or sets the predicate that determines whether or not a string of text is valid. * If this is non-null, this predicate is called in addition to any {@link TextBlock.textValidation} predicate. * See {@link isValidText} for more details. * The default predicate is null, which is equivalent to simply returning true. * * The function, if supplied, must not have any side-effects. */ get textValidation(): ((aTextBlock: TextBlock, oldString: string, newString: string) => boolean) | null; set textValidation(value: ((aTextBlock: TextBlock, oldString: string, newString: string) => boolean) | null); set minimumEditorScale(value: number); /** * Gets or sets whether to select (highlight) the editable text when the TextEditingTool is activated. * The default is true. */ get selectsTextOnActivate(): boolean; set selectsTextOnActivate(value: boolean); /** * Gets or sets the state of the TextEditingTool. * The only accepted values are {@link TextEditingState} values. * * The starting value value is {@link TextEditingState.None}, * {@link TextEditingTool.doActivate} sets the value to {@link TextEditingState.Active}. * The default text editor receiving focus sets the value to {@link TextEditingState.Editing}. * {@link TextEditingTool.acceptText} sets the value to {@link TextEditingState.Validating}. * Once accepted and the tool begins the "TextEditing" transaction, the value is set to {@link TextEditingState.Validated}. */ get state(): TextEditingState; set state(value: TextEditingState); /** * This method returns a temporary {@link TextBlock} used for measuring text during editing. * The TextBlock.text is set to the parameter's value, * and the TextBlock is measured with the last available width of the {@link textBlock}. * * Text editors can use the {@link GraphObject.measuredBounds} and {@link TextBlock.lineCount} * to determine a reasonable size for their text areas. * @param text - the text to measure */ measureTemporaryTextBlock(text: string): TextBlock; } /** * An EasingFunction describes how much to modify a scalar value based on * the current time, the start value, the change in value, and the duration. */ export type EasingFunction = ((currentTime: number, startValue: number, byValue: number, duration: number) => number); /** * This enumeration specifies possible values for {@link AnimationManager.initialAnimationStyle}. * * To customize the initial animation, set {@link AnimationManager.initialAnimationStyle} to {@link None} * and define an `"InitialAnimationStarting"` DiagramEvent listener with {@link Diagram.addDiagramListener}. * * See {@link AnimationManager.initialAnimationStyle} for details and examples. * @since 3.0 */ export declare enum AnimationStyle { /** * The default initial animation style will "fade up" and in the Diagram's contents by animating the {@link Diagram.position} and {@link Diagram.opacity}. */ Default = 1, /** * This value will cause initial animations to capture Part locations and animate them from `(0, 0)` to those location values. * This was the default initial animation behavior in GoJS 2.0 and prior. */ AnimateLocations = 2, /** * This will turn off the initial animation, but also allows for customizing the initial animation by adding your own properties * if you define an `"InitialAnimationStarting"` listener with {@link Diagram.addDiagramListener}. */ None = 3 } /** * AnimationManager handles animations in a {@link Diagram}. Each Diagram has one, {@link Diagram.animationManager}. * Setting the Model, performing a Layout, Group expansion and Tree expansion automatically start animations through * the {@link defaultAnimation}. Animations can be manually started by creating {@link Animation}s, which are associated with an * AnimationManager. * * Animation is enabled by default, setting the {@link isEnabled} property to false will turn off animations for a Diagram. * * When the {@link defaultAnimation} begins it raises the `"AnimationStarting"` Diagram event, * upon completion it raises the `"AnimationFinished"` Diagram event. * * The {@link defaultAnimation}, if running, will stop if a new transaction is started, if an undo or redo is called, * if a layout is invalidated, or if a model is replaced. * When an {@link Animation} is stopped, the Diagram immediately finishes the animation and draws the final state. * Animations can be stopped programmatically with the methods {@link AnimationManager.stopAnimation} or {@link Animation.stop}. */ export class AnimationManager { /** * You do not normally need to create an instance of this class because one already exists as the {@link Diagram.animationManager}, which you can modify. * @param init - Optional initialization properties. * This is typically only used in the {@link Diagram} constructor to set properties on the {@link Diagram.animationManager}. */ constructor(init?: Partial); /** * This method is passed the reason a default animation is to begin, * and must return true or false based on whether or not the animation is to be allowed. * Returning true means the animation will occur, returning false will stop the animation's setup. * * By default, this method always returns true. * Setting this to a function that always returns false will disable all default animations, * but allow other animations, such as {@link AnimationTrigger}s, to run. * * These are the possible reasons GoJS will begin an animation: * * **Called by CommandHandler:** * - "Collapse SubGraph" * - "Expand SubGraph" * - "Collapse Tree" * - "Expand Tree" * - "Scroll To Part" * - "Zoom To Fit" * * **Called by Diagram:** * - "Model" * - "Layout" * * **Called by AnimationTriggers:** * - "Trigger" * * Example usage: * * ```js * // disallow expand/collapse animations, but allow all other default animations: * myDiagram.animationManager.canStart = function(reason) { * if (reason === "Expand Tree") return false; * return true; * } * * // disallow all default animations: * myDiagram.animationManager.canStart = function(reason) { * return false; * } * ``` * @param reason - Reason for starting the animation * @since 2.1 */ canStart(reason: string): boolean; /** * @virtual * Undocumented * Returns the current bundled animation */ getBundleAnimation(): Animation; /** * Stops the {@link defaultAnimation} and updates the Diagram to its final state. * * If the argument is true, this stops all running animations. * If an Animation was about to begin, it will be cancelled. * * If the {@link AnimationManager.defaultAnimation} is running, this will raise the `"AnimationFinished"` Diagram event. * @param stopsAllAnimations - Whether to stop all animations, instead of just the {@link defaultAnimation}. Default false. */ stopAnimation(stopsAllAnimations?: boolean): void; /** * Gets or sets whether this AnimationManager operates. * * The default value is `true`. * Setting this to `false` does not stop an animation, it only stops future animations. * To stop any ongoing animation, use {@link stopAnimation}. * To disable only the default animations, set {@link canStart} to a function that always returns `false`. * * If any indefinite animations (animations with {@link Animation.runCount} set to `Infinity`) were running * when this is set to `false`, they will be resumed when this is set to `true`. * * Setting this property does not raise any events. * @see {@link canStart} */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * Gets or sets the default duration, in milliseconds, used as the duration for the {@link defaultAnimation} * and for animations that have their {@link Animation.duration} set to `NaN`. * * Typically these values are short. The default value is 600 milliseconds. * The value must be a number greater than or equal to 1. * Setting this property does not raise any events. * * @see {@link Animation.duration} */ get duration(): number; set duration(value: number); /** * This read-only property is true when the animation manager is currently animating any animation, * including the {@link defaultAnimation}. * * This value cannot be set, but animation can be stopped by calling {@link stopAnimation}, * and it can be prevented by setting {@link isEnabled}. */ get isAnimating(): boolean; /** * This read-only property is true when the animation manager is in the middle of an animation tick. * Animation only operates on GraphObjects during ticks, but code outside of AnimationManager's control may execute between ticks. * * `isTicking` can only be true when {@link isAnimating} is also true. */ get isTicking(): boolean; /** * Gets or sets whether a default animation is performed on an initial layout. * * The default value is true. * Changing the value does not affect any ongoing animation. * Setting this property does not raise any events. */ get isInitial(): boolean; set isInitial(value: boolean); /** * This read-only property gets the {@link Animation} that carries out the default built-in GoJS animations. * This animation is usually only referenced to modify default animation properties, * such as the {@link Animation.easing} or {@link Animation.duration}. * * You should not add anything to or start the default animation, GoJS does so automatically, internally. * When the default animation begins it raises the `"AnimationStarting"` Diagram event, * upon completion it raises the `"AnimationFinished"` Diagram event. * You should not modify the properties {@link Animation.runCount} or {@link Animation.reversible} on the default animation. * * See the Introduction Page on Animations for more detail. * @since 2.1 */ get defaultAnimation(): Animation; /** * Gets the set of currently animating {@link Animation}s being managed by this AnimationManager, including any running {@link defaultAnimation}. * @since 2.1 */ get activeAnimations(): Set; /** * Gets or sets the initial animation style that is set up by the {@link defaultAnimation}. * This can be {@link AnimationStyle.Default}, {@link AnimationStyle.AnimateLocations}, or {@link AnimationStyle.None}. * - If set to {@link AnimationStyle.Default}, the initial animation will "fade up" * the Diagram's contents by animating the {@link Diagram.position} and {@link Diagram.opacity}. * - If set to {@link AnimationStyle.AnimateLocations}, the initial animation will animate Part locations from `(0, 0)` to their values, as GoJS 2.0 and prior do. * - If set to {@link AnimationStyle.None}, no initial animation will happen by default, * which this allows you to specify your own initial animation by defining a `"InitialAnimationStarting"` DiagramEvent listener with {@link Diagram.addDiagramListener}. * * An example custom initial animation, which zooms the Diagram into view: * * ```js * myDiagram.animationManager.initialAnimationStyle = go.AnimationStyle.None; * myDiagram.addDiagramListener('InitialAnimationStarting', e => { * const animation = e.subject.defaultAnimation; * animation.easing = go.Animation.EaseOutExpo; * animation.duration = 900; * animation.add(e.diagram, 'scale', 0.1, 1); * animation.add(e.diagram, 'opacity', 0, 1); * }); * ``` * * * @since 2.1 */ get initialAnimationStyle(): AnimationStyle; set initialAnimationStyle(value: AnimationStyle); /** * Defines a new named effect to be used in animation, along with a function that tells the AnimationManager how to modify that property. * * Effect names do not need to reflect GraphObject properties, and you can define an effect with a function that modifies several properties for convenience. * * For example, one could define an animation effect named `"moveAndSpin"` which modifies the object's `position` and `angle`. * * Most commonly, an effect is defined with one GraphObject property in mind to be animated, * and the function uses the start and end values, an easing function, and the times to determine a new value for each tick of animation. * Here is an example for animating the fill of GraphObjects: * * ```js * // This presumes the object to be animated is a Shape * go.AnimationManager.defineAnimationEffect('fill', (obj, startValue, endValue, easing, currentTime, duration, animation) => { * const hueValue = easing(currentTime, startValue, endValue - startValue, duration); * obj.fill = 'hsl(' + hueValue + ', 100%, 80%)'; * }); * ``` * * @param effectName - Named effect to animate * @param animationFunction - Function * that transforms the property values. It takes the animated object, start value, end value, * easing function (the {@link Animation.easing}), current time, duration, and animation state. It should modify one or more properties on the object. * @since 2.1 */ static defineAnimationEffect(effectName: string, animationFunction: (obj: Diagram | GraphObject, startValue: any, endValue: any, easing: EasingFunction, currentTime: number, duration: number, animation: Animation) => void): void; /** * @deprecated See {@link AnimationStyle.Default}. */ static readonly Default = AnimationStyle.Default; /** * @deprecated See {@link AnimationStyle.AnimateLocations}. */ static readonly AnimateLocations = AnimationStyle.AnimateLocations; /** * @deprecated See {@link AnimationStyle.None}. */ static readonly None = AnimationStyle.None; } /** * Animations are used to animate {@link GraphObject} and {@link Diagram} properties. * * This class is useful for creating manual animations. * If you wish to animate particular properties on a GraphObject every time their value changes, * you may want to use {@link AnimationTrigger}s instead, which automatically create and start Animations. * * The {@link AnimationManager.defaultAnimation} is an instance of this class, and carries out the * default animations in GoJS: Model load, layout, expand and collapse, and so on. * See the Introduction Page on Animations for more detail on the different kinds of animations. * * Manual animations are set up by creating an instance of this class, and calling {@link add} at least once, then calling {@link start}. * The method {@link add} specifies which objects and which animation effects/properties to animate, plus start and end values for the property. * As objects are added to an Animation, the Animation infers which {@link Diagram} and {@link AnimationManager} is relevant. * * Animations are started by calling {@link start}, and stopped when the {@link duration} is reached, or when {@link stop} is called, * or stopped when {@link AnimationManager.stopAnimation} is called with `true` as its argument. * * Animations can continue indefinitely if {@link runCount} is set to `Infinity`. * Animations can act upon temporary copies of an object that will get destroyed by calling {@link addTemporaryPart}. * This is useful when crafting cosmetic animations of parts that are about to be deleted: * Since the part will no longer exist, you can instead animate a temporary part disappearing. * * A simple example usage is this: * ```js * const node = myDiagram.nodes.first(); * const shape = part.findObject("SHAPE"); // assumes this Node contains a go.Shape with .name = "SHAPE" * const animation = new go.Animation(); * // Animate this Node from its current position to (400, 500) * animation.add(node, "position", node.position, new go.Point(400, 500)); * // Animate the fill of the Shape within the Node, from its current color to blue * animation.add(shape, "fill", shape.fill, "blue"); * // Both of these effects will animate simultaneously when start() is called: * animation.start(); * ``` * * See the Introduction Page on Animations and the Custom Animations sample * for more example usage of the Animation class. * * Unlike the {@link AnimationManager.defaultAnimation}, Animations can be started any time, * and do not stop automatically when a new transaction begins. * @since 2.1 */ export class Animation { /** * The constructor creates an Animation. * A single Animation can animate multiple objects via multiple calls to {@link add}. * When you are ready to begin the animation, call {@link start}. * @param init - Optional properties to initialize. */ constructor(init?: Partial); /** * @virtual * (undocumented) Debug only. */ suspend(): void; /** * @virtual * (undocumented) Debug only. */ advanceTo(duration: number, resume?: boolean): void; /** * Start this animation. * * This adds the Animation to its {@link AnimationManager}'s list of active animations. * The AnimationManager is inferred from the list of objects to be animated, by inspecting their Diagram. * * This does nothing if there are no objects to animate. * @returns this Animation */ start(): this; /** * Add a temporary Part to this animation. * This part will be added to the Diagram when the animation is started, * and removed from the Diagram when the animation completes. * This is intended to be used with {@link add}, to animate properties of this Part or its elements. * * The temporary part added is typically either a {@link GraphObject.copy} of an existing Part, * which is to be deleted and requires a copy for animated effects, or else a wholly new temporary Part, * constructed in memory for the purpose of creating some effect. * @param part - A part to add to the Diagram at the start of the animation and remove at the end. * This is typically either a copied Part already in the Diagram, to animate its deletion, * or a Part created programmatically to be used for some effect. * @param diagram - The Diagram to add the temporary part to, and remove it from, at the start and end of animation, respectively. * @returns this Animation */ addTemporaryPart(part: Part, diagram: Diagram): this; /** * Add an object (GraphObject or Diagram) and effect name, with specified start and end values, to this Animation. * * @param obj - GraphObject or Diagram to animate. * @param effectName - Animation effect name, such as `"scale"` to change GraphObject.scale. * By default the supported properties are, for GraphObjects: * * `"position"` * * `"location"` (on Parts) * * `"scale"` * * `"opacity"` * * `"angle"` * * `"desiredSize"` * * `"width"` * * `"height"` * * `"background"` * * `"fill"` (on Shapes) * * `"strokeWidth"` (on Shapes) * * `"strokeDashOffset"` (on Shapes) * * `"stroke"` (on Shapes, TextBlocks) * * For Diagrams: * * `"position"` * * `"scale"` * * `"opacity"` * * More properties can be supported by defining new effects with {@link AnimationManager.defineAnimationEffect}. * @param startValue - The starting value for the animated property. Often this is the current value of the property. * @param endValue - The ending value for the animated property. Even if the animation is just cosmetic, this must be a valid value for the property. * For instance, for {@link GraphObject.scale}, you cannot animate to 0, as this is an invalid scale value. * Instead you would animate to a very small (but still valid) value, such as 0.001. * @param cosmetic - Determines if the animation should revert the property value to the start value at the end of animation. * Default false. This is commonly used when animating opacity or scale of "disappearing" nodes during collapse. * Even though the node may appear to go to scale 0.001, the programmer usually wants the scale to reflect its prior value, once hidden. * @returns this Animation */ add(obj: GraphObject | Diagram, effectName: string, startValue: any, endValue: any, cosmetic?: boolean): this; /** * Stops a running Animation and updates the animating objects to their final state. * * If an animation was about to begin, it is cancelled. * @returns this Animation */ stop(): this; /** * Gets or sets the duration for animations, in milliseconds. * * The default value is `NaN`, which means it inherits the default value from the {@link AnimationManager.duration}, * which defaults to 600 milliseconds. * * The value must be a number greater than or equal to 1, or `NaN`. * Setting this property does not raise any events. */ get duration(): number; set duration(value: number); /** * Gets or sets whether this Animation will repeat its animation in reverse at the end of the duration. Default false. * * A reversible Animation, if stopped early, will end at its original state. * Setting this to true doubles the effective {@link duration} of the Animation. * * This property should not be set on the {@link AnimationManager.defaultAnimation} */ get reversible(): boolean; set reversible(value: boolean); /** * Gets or sets whether this Animation should be repeat, and how many times. The default is 1, which means the animation does not repeat. * * This can be set to any non-zero positive integer, or `Infinity`. Setting this to `Infinity` will repeat an animation forever. * * This property should not be set on the {@link AnimationManager.defaultAnimation} * * @see {@link reversible} */ get runCount(): number; set runCount(value: number); /** * Gets or sets the function to execute when the user Animation finishes. * * By default this property is null. */ get finished(): ((animation: Animation) => void) | null; set finished(value: ((animation: Animation) => void) | null); /** * Gets or sets the easing function this Animation will use to modify default properties. * * Pre-defined animatable values are processed by passing scalars into this easing function. * * The default value is {@link Animation.EaseInOutQuad}. * * * The value can be an arbitrary easing function, or one of the six provided: * {@link Animation.EaseLinear}, {@link Animation.EaseInOutQuad}, {@link Animation.EaseInQuad}, * {@link Animation.EaseOutQuad}, {@link Animation.EaseInExpo}, {@link Animation.EaseOutExpo}. * */ get easing(): EasingFunction; set easing(value: EasingFunction); /** * Gets or sets whether this Animation should allow an unconstrained viewport during the runtime of the animation. * This temporarily sets the {@link Diagram.scrollMode} to {@link ScrollMode.Infinite}, and restores the value at the end of the animation. * This is done so that animating objects can move out of the viewport temporarily during the animation and not trigger scrollbars. * * This may be useful to set for animations that have objects or the Diagram bounds animate from outside the viewport into the view. * The default value is true. */ get isViewportUnconstrained(): boolean; set isViewportUnconstrained(value: boolean); /** * This read-only property is true when the Animation is currently running. * * This value cannot be set, but Animation can be stopped by calling {@link stop}. */ get isAnimating(): boolean; /** * Gets the {@link ObjectData} associated with this GraphObject or Diagram. * If no state exists, this creates and returns a new {@link ObjectData}. * * This can be used to store temporary information per animated object during the course of an animation. * This state is cleared at the end of an animation. */ getTemporaryState(obj: GraphObject | Diagram): ObjectData; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * @constant */ static EaseLinear: EasingFunction; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * This is the default value for {@link Animation.easing}. * @constant */ static EaseInOutQuad: EasingFunction; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * @constant */ static EaseInQuad: EasingFunction; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * @constant */ static EaseOutQuad: EasingFunction; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * @constant */ static EaseInExpo: EasingFunction; /** * Built-in static function for computing interpolated values. Can be used as a value for {@link Animation.easing}. * @constant */ static EaseOutExpo: EasingFunction; } /** * This enumeration specifices how an animation should be triggered. * Used for {@link AnimationTrigger.startCondition}. * @since 3.0 */ export declare enum TriggerStart { /** * GoJS will use {@link Bundled} or {@link Immediate} based on the state of the transaction. * If no transaction is ongoing, this trigger will be treated as using {@link Immediate}, * otherwise it will work as {@link Bundled}. */ Default = 1, /** * A new animation will be created for every instance of the property changing, and started immediately, * and run until completion. This may be useful for cosmetic changes, such as animating * the opacity or color of an object on mouseEnter or mouseLeave. * However, using {@link Bundled} may be more efficient, as it will create fewer animations. */ Immediate = 2, /** * The AnimationManager will use the default animation to prepare a single Animation that begins when the current transaction has ended. * This animation may be canceled if a new transaction is started. */ Bundled = 3 } /** * An AnimationTrigger describes how to automatically animate a property on a {@link GraphObject} * when it changes value. * The target property name is a string, and all name matching is case-sensitive. * * Triggers will be shared by all copies of the template's GraphObjects. * You can include AnimationTriggers in your templates just like {@link Binding}s are included: * * ```js * new go.Panel("Vertical", * { * // ... Panel properties * }) * // This trigger uses the default value of AnimationTrigger.startCondition: * // If a transaction is ongoing and Panel.position is changed, this trigger will animate * // all changes to Panel.position at the end of the next transaction, in one bundled Animation. * // If no transaction is ongoing, then it will animate this value immediately. * .trigger("position") * .add( * new go.Shape({ * // ... Shape properties * }) * // Animate all changes to Shape.opacity immediately * .trigger("opacity", null, go.TriggerStart.Immediate), * // ... other GraphObjects in the Panel * ) * ``` * When the {@link startCondition} is {@link TriggerStart.Default}, * GoJS will attempt to {@link TriggerStart.Bundled} or {@link TriggerStart.Immediate} based on the state of the transaction. * If no transaction is ongoing, this trigger will treat the default as using {@link TriggerStart.Immediate}. * Otherwise it will work as {@link TriggerStart.Bundled}. * * When the {@link startCondition} is {@link TriggerStart.Bundled}, * the AnimationManager will use the default animation to prepare a single Animation that begins when the current transaction has ended. * This animation may be canceled if a new transaction is started. * * When the {@link startCondition} is {@link TriggerStart.Immediate}, * a new animation will be created for every instance of the property changed, and started immediately, * and run until completion. This may be useful for cosmetic changes, such as animating * the opacity or color of an object on mouseEnter or mouseLeave. * * You can only specify properties that exist on the GraphObject, and are also registered with {@link AnimationManager.defineAnimationEffect}. * By default these properties are: * * * `"position"` * * `"location"` (on Parts) * * `"scale"` * * `"opacity"` * * `"angle"` * * `"desiredSize"` * * `"background"` * * `"fill"` (on Shapes) * * `"strokeWidth"` (on Shapes) * * `"strokeDashOffset"` (on Shapes) * * `"stroke"` (on Shapes, TextBlocks) * * Examples of defining additional animation properties are given in the Introduction Page on Animations. * @since 2.1 */ export class AnimationTrigger { /** * This constructor creates an AnimationTrigger. These are typically constructed within Part templates. * * ```js * // ... * new go.Shape( * { * // ... Shape properties * }) * // Animate all changes to Shape.opacity immediately * .trigger("opacity", null, go.TriggerStart.Immediate) * ``` * @param propertyName - A string naming the target property to animate. * This should not be the empty string. * @param animationSettings - An optional Object describing properties to set on animations created by this AnimationTrigger. * See the {@link animationSettings} property for detail. * If specified, this also sets the {@link startCondition} to {@link TriggerStart.Immediate}. * @param startCondition - An optional TriggerStart to set the {@link startCondition} property. */ constructor(propertyName: string, animationSettings?: { duration?: number; finished?: (animation: Animation) => void; easing?: EasingFunction; }, startCondition?: TriggerStart); /** * Create a copy of this AnimationTrigger, with the same property values. * @virtual */ copy(): AnimationTrigger; /** * Gets or sets the name of the property to animate on the target {@link GraphObject}. * The default value is set during constructor initialization. * * You can only specify properties that exist on the GraphObject, and are also registered with {@link AnimationManager.defineAnimationEffect}. * By default these properties are the same as the list of possible Animation effects: * * * `"position"` * * `"location"` (on Parts) * * `"scale"` * * `"opacity"` * * `"angle"` * * `"desiredSize"` * * `"background"` * * `"fill"` (on Shapes) * * `"strokeWidth"` (on Shapes) * * `"strokeDashOffset"` (on Shapes) * * `"stroke"` (on Shapes, TextBlocks) * * Examples of defining additional properties by adding animation effects are given in the Introduction Page on Animations. */ get propertyName(): string; set propertyName(value: string); /** * These settings are only used if the {@link startCondition} is {@link TriggerStart.Immediate}. * Creating a new AnimationTrigger with animationSettings in the constructor automatically sets {@link startCondition} to {@link TriggerStart.Immediate} * * This gets or sets the settings for any {@link Animation}s this trigger creates. * Immediate triggers create a new Animation with each triggering, and apply these settings to that Animation. * * This can be set to an object with a subset of possible {@link Animation} settings. The default value is `null`, which keeps default Animation settings. * * Since a {@link startCondition} of {@link TriggerStart.Bundled} uses the default animation, * you must set the properties of {@link AnimationManager.defaultAnimation}, and not this property, to modify the animation settings. * * To set default settings for *all* created Animations, you can modify the settings on {@link AnimationManager} instead, such as {@link AnimationManager.duration}. * * Possible properties to set in this object are: * * * **duration**: a `number`, corresponding to {@link Animation.duration}. * * **finished**: a `Function`, corresponding to {@link Animation.finished}. * * **easing**: an `EasingFunction`, corresponding to {@link Animation.easing}. */ get animationSettings(): { duration?: number; finished?: (animation: Animation) => void; easing?: EasingFunction; }; set animationSettings(value: { duration?: number; finished?: (animation: Animation) => void; easing?: EasingFunction; }); /** * Gets or sets the starting condition for this trigger. * * AnimationTriggers can invoke an animation immediately, * starting a new animation with each property of each GraphObject that has been modified, * or they can (more efficiently) be bundled together into the default animation ({@link AnimationManager.defaultAnimation}) * and begin only one animation, at the end of the next transaction. * * It is useful for the startCondition to be {@link TriggerStart.Immediate} when changing GraphObject properties * on {@link GraphObject.mouseEnter} or {@link GraphObject.mouseLeave}. * It is useful for the startCondition to be {@link TriggerStart.Bundled} when changing several GraphObject properties together, * such as when highlighting multiple parts, on selection changes, and during transactions, or when performance is a consideration. * * These behaviors can be set with the values {@link TriggerStart.Immediate} and {@link TriggerStart.Bundled}, respectively. * The default value, {@link TriggerStart.Default}, attempts to infer which is best: * It will start immediately if there is no ongoing transaction * or if {@link Diagram.skipsUndoManager} is true, and otherwise bundle them. */ get startCondition(): TriggerStart; set startCondition(value: TriggerStart); /** * @deprecated See {@link TriggerStart.Default}. */ static readonly Default = TriggerStart.Default; /** * @deprecated See {@link TriggerStart.Immediate}. */ static readonly Immediate = TriggerStart.Immediate; /** * @deprecated See {@link TriggerStart.Bundled}. */ static readonly Bundled = TriggerStart.Bundled; } /** * Layers are how named collections of {@link Part}s are drawn in front or behind other collections of Parts in a {@link Diagram}. * Layers can only contain {@link Part}s, such as {@link Node}s and {@link Link}s. They cannot hold {@link GraphObject}s directly. * * Layers have many properties that control what actions users are permitted to perform involving the parts in the layer. * These properties are very much like the similarly named properties on {@link Diagram}. * * You put a Part into a Layer by assigning {@link Part.layerName} with the name of the Layer. * You can use data binding to initialize and remember a Part's layer's name. * You can change a Part's layer by modifying its {@link Part.layerName}, which changes its {@link Part.layer}. * A Part cannot be in more than one Layer at a time. * * Each Diagram starts off with the following list of Layers: *

    *
  • "Grid"
  • *
  • "ViewportBackground"
  • *
  • "Background"
  • *
  • "" (the default layer)
  • *
  • "Foreground"
  • *
  • "ViewportForeground"
  • *
  • "Adornment"
  • *
  • "Tool"
  • *
* * Layers are drawn and presented in order. * Parts are normally put in the default layer. * * The "Grid" layer is the furthest back; it also contains "temporary" parts that cannot be selected. * Furthermore the "Grid" layer has {@link pickable} set to false so that mouse or touch events * and calls to the "find..." hit-testing methods do not even consider any parts in that layer. * * The "Grid", "Adornment", "Tool", and both "Viewport..." layers are considered {@link isTemporary}. * Changes to objects in temporary layers are not recorded by the {@link UndoManager}. * Parts in temporary layers are not selected. * Objects in temporary layers do not receive click events unless you set their {@link GraphObject.isActionable} to true. * * Use {@link Diagram.findLayer} to get the Layer with a particular name. * You can add your own layers by calling {@link Diagram.addLayerBefore} or {@link Diagram.addLayerAfter} * to insert a new layer at a particular place in the Z-order, or to re-order existing layers. * {@link Part}s can be individually z-ordered within a layer by setting {@link Part.zOrder}. */ export class Layer { /** * This constructs an empty Layer; you should set the {@link name} before adding the Layer to a Diagram. * @param init - Optional properties to initialize. */ constructor(init?: Partial); /** * Find the front-most {@link GraphObject} in this layer * at the given point in document coordinates. * * If {@link visible} is false, this method will not find any objects in this layer. * However, {@link opacity} does not affect this method. * @param p - A Point in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @returns The first GraphObject in the Z-order, or else null. */ findObjectAt(p: Point, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null): (T | null); /** * Return a collection of the {@link GraphObject}s of this layer * at the given point in document coordinates. * * If {@link visible} is false, this method will not find any objects in this layer. * However, {@link opacity} does not affect this method. * @param p - A Point in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects that will contain all GraphObjects * located at Point p, or else an empty collection. * If a List or Set was passed in, it is returned. */ findObjectsAt | Set = Set>(p: Point, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, coll?: S): S; /** * Returns a collection of all {@link GraphObject}s that are inside or that intersect * a given {@link Rect} in document coordinates. * * If {@link visible} is false, this method will not find any objects in this layer. * However, {@link opacity} does not affect this method. * @param r - A Rect in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param partialInclusion - Whether an object can match if it merely intersects the rectangular area (true) or * if it must be entirely inside the rectangular area (false). The default value is false. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects that will contain all GraphObjects * located in or near Rect r, or else an empty collection. * If a List or Set was passed in, it is returned. */ findObjectsIn | Set = Set>(r: Rect, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, partialInclusion?: boolean, coll?: S): S; /** * Returns a collection of all {@link GraphObject}s that are within a certain distance * of a given point in document coordinates. * * If {@link visible} is false, this method will not find any objects in this layer. * However, {@link opacity} does not affect this method. * @param p - A Point in document coordinates. * @param dist - The distance from the point. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param partialInclusion - Whether an object can match if it merely intersects the circular area (true) or * if it must be entirely inside the circular area (false). The default value is true. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects that will contain all GraphObjects * located at Point p, or else an empty collection. * If a List or Set was passed in, it is returned. */ findObjectsNear | Set = Set>(p: Point, dist: number, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, partialInclusion?: boolean | S, coll?: S): S; /** * This read-only property returns an iterator for this Layer's {@link Part}s. * The Parts can be {@link Node}s, {@link Link}s, {@link Group}s, {@link Adornment}s, or simple {@link Part}s. */ get parts(): Iterator; /** * This read-only property returns a backwards iterator for this Layer's {@link Part}s, * for iterating over the parts in reverse order. * The Parts can be {@link Node}s, {@link Link}s, {@link Group}s, {@link Adornment}s, or simple {@link Part}s. */ get partsBackwards(): Iterator; /** * This read-only property returns the {@link Diagram} that is using this Layer. */ get diagram(): Diagram | null; /** * Gets or sets the name for this layer. * The initial value is an empty string, which is also the name of the default layer. * The name should be unique among the diagram's {@link Diagram.layers}. */ get name(): string; set name(value: string); /** * Gets or sets the opacity for all parts in this layer. * The value must be between 0.0 (fully transparent) and 1.0 (no additional transparency). * This value is multiplicative with any existing transparency, * for instance from a {@link Brush} or image transparency. * The default value is 1. * * This property, unlike {@link visible}, does not change whether any objects are found by the "find..." methods. * @see {@link GraphObject.opacity} * @see {@link Diagram.opacity} * @see {@link visible} */ get opacity(): number; set opacity(value: number); /** * Gets or sets whether this layer enforces its Parts to remain in viewport coordinates. * Diagrams have two default layers with this set to `true`: "ViewportBackground" and "ViewportForeground". * These layers also have {@link isInDocumentBounds} set to `false` and {@link isTemporary} set to `true`. * If you set this property on a layer, you may wish to set those properties also. * * Parts in viewport coordinate layers will get their positions and scales set automatically, * to remain invariantly placed and sized in the viewport. * * Instead of position, Parts are placed by setting their {@link GraphObject.alignment} and * {@link GraphObject.alignmentFocus} values in the same way they are used in a * [Spot Panel](../../intro/panels.html#Spots). * However, the alignment spot, if it is {@link Spot.Default} as it is by default, * will be treated as {@link Spot.BottomRight} rather than {@link Spot.Center} * as a "Spot" Panel does. * The alignmentFocus spot, if it is {@link Spot.Default} as it is by default, * will be treated as the same Spot as the alignment without any offset. * This is convenient for aligning Parts along the sides of the viewport. * If you wish to arrange a Part to be near the side of the viewport at a certain distance, * specify that in the alignment Spot. * For example, the following code places the red circle near the bottom right corner, * but inset by 10 units from both the right and the bottom sides. * ```js * myDiagram.add( * new go.Part({ * layerName: "ViewportBackground", * alignment: new go.Spot(1, 1, -10, -10) * }).add( * new go.Shape("Circle", { fill: "red", width: 20, height: 20 }) * ) * ); * ``` * * For example usage, see [Legends and Titles](../../intro/legends.html). * * Parts in viewport coordinate layers may have unexpected interactions if they are * connected to Parts in non-viewport coordinate layers. * Setting this value to true automatically sets {@link isInDocumentBounds} to `false`. * * @since 3.0 * @defaultValue `false` */ get isViewportAligned(): boolean; set isViewportAligned(value: boolean); /** * Gets or sets whether the objects in this layer are considered temporary. * * Parts in temporary layers are not selectable, * and changes to Parts in temporary layers are not recorded in the {@link UndoManager}. * Objects in temporary layers do not receive click events unless you set their {@link GraphObject.isActionable} to true. * * Default value is false. * * As of v3.0, setting this property to true no longer sets {@link isInDocumentBounds} on this layer set to false. * You may want to set this property to false on temporary Layers. * @see {@link isInDocumentBounds} */ get isTemporary(): boolean; set isTemporary(value: boolean); /** * Gets or sets whether the user may view any of the objects in this layer. * * The default value is true -- all visible Parts are drawn. * When this property is false, all of the "find..." methods will fail to find parts that are in this layer. * @see {@link GraphObject.visible} * @see {@link opacity} * @see {@link pickable} */ get visible(): boolean; set visible(value: boolean); /** * Gets or sets whether methods such as {@link findObjectAt} find any of the objects in this layer. * * When this property is false, all of the "find..." methods will fail to find parts that are in this layer. * The default value is true. * All of the predefined Layers have this property true, except for the "Grid" Layer. * * Note that setting pickable to false does not prevent users from selecting nodes. * It does prevent them from selecting nodes by clicking on them, * but does not prevent selection through other mechanisms such as the {@link DragSelectingTool} or * {@link CommandHandler.selectAll} or calls to {@link Diagram.select}. * * You can control whether individual GraphObjects are "hittable" by setting {@link GraphObject.pickable}. * @see {@link GraphObject.pickable} * @see {@link visible} */ get pickable(): boolean; set pickable(value: boolean); /** * Gets or sets whether or not a layer is included in the {@link Diagram.documentBounds} computation. * * Default value is `true`. * All of the predefined temporary Layers have this property false, except for the "Tool" Layer. * @since 2.2 * @see {@link isTemporary} */ get isInDocumentBounds(): boolean; set isInDocumentBounds(value: boolean); /** * Gets or sets whether the user may copy objects in this layer. * The initial value is true. * @see {@link Part.copyable} * @see {@link Part.canCopy} * @see {@link Diagram.allowCopy} */ get allowCopy(): boolean; set allowCopy(value: boolean); /** * Gets or sets whether the user may delete objects in this layer. * The initial value is true. * @see {@link Part.deletable} * @see {@link Part.canDelete} * @see {@link Diagram.allowDelete} */ get allowDelete(): boolean; set allowDelete(value: boolean); /** * Gets or sets whether the user may do in-place text editing in this layer. * The initial value is true. * @see {@link Part.textEditable} * @see {@link Part.canEdit} * @see {@link Diagram.allowTextEdit} */ get allowTextEdit(): boolean; set allowTextEdit(value: boolean); /** * Gets or sets whether the user may group parts together in this layer. * The initial value is true. * @see {@link Part.groupable} * @see {@link Part.canGroup} * @see {@link Diagram.allowGroup} */ get allowGroup(): boolean; set allowGroup(value: boolean); /** * Gets or sets whether the user may ungroup existing groups in this layer. * The initial value is true. * @see {@link Group.ungroupable} * @see {@link Group.canUngroup} * @see {@link Diagram.allowUngroup} */ get allowUngroup(): boolean; set allowUngroup(value: boolean); /** * Gets or sets whether the user may draw new links in this layer. * The initial value is true. * @see {@link Diagram.allowLink} */ get allowLink(): boolean; set allowLink(value: boolean); /** * Gets or sets whether the user may reconnect existing links in this layer. * The initial value is true. * @see {@link Link.relinkableFrom} * @see {@link Link.relinkableTo} * @see {@link Link.canRelinkFrom} * @see {@link Link.canRelinkTo} * @see {@link Diagram.allowRelink} */ get allowRelink(): boolean; set allowRelink(value: boolean); /** * Gets or sets whether the user may move objects in this layer. * The initial value is true. * @see {@link Part.movable} * @see {@link Part.canMove} * @see {@link Diagram.allowMove} */ get allowMove(): boolean; set allowMove(value: boolean); /** * Gets or sets whether the user may reshape parts in this layer. * The initial value is true. * @see {@link Part.reshapable} * @see {@link Part.canReshape} * @see {@link Diagram.allowReshape} */ get allowReshape(): boolean; set allowReshape(value: boolean); /** * Gets or sets whether the user may resize parts in this layer. * The initial value is true. * @see {@link Part.resizable} * @see {@link Part.canResize} * @see {@link Diagram.allowResize} */ get allowResize(): boolean; set allowResize(value: boolean); /** * Gets or sets whether the user may rotate parts in this layer. * The initial value is true. * @see {@link Part.rotatable} * @see {@link Part.canRotate} * @see {@link Diagram.allowRotate} */ get allowRotate(): boolean; set allowRotate(value: boolean); /** * Gets or sets whether the user may select objects in this layer. * The initial value is true. * * All of the predefined Layers have this property set to true, except for the "Grid" Layer. * @see {@link Part.selectable} * @see {@link Part.canSelect} * @see {@link Diagram.allowSelect} */ get allowSelect(): boolean; set allowSelect(value: boolean); } /** * DiagramInitOptions are used in the Diagram constructor to concisely initialize a Diagram by settings its properties, * and also set properties on its Tools, CommandHandler, AnimationManager, and set DiagramEvents. */ export type DiagramInitOptions = Partial; /** */ export type DiagramEvents = { [P in DiagramEventName]?: DiagramEventHandler; }; interface DiagramInitStrings { [index: string]: any; 'animationManager.isEnabled'?: boolean; 'animationManager.duration'?: number; 'animationManager.isInitial'?: boolean; 'animationManager.initialAnimationStyle'?: AnimationStyle; 'commandHandler.copiesClipboardData'?: boolean; 'commandHandler.copiesConnectedLinks'?: boolean; 'commandHandler.deletesConnectedLinks'?: boolean; 'commandHandler.copiesTree'?: boolean; 'commandHandler.deletesTree'?: boolean; 'commandHandler.copiesParentKey'?: boolean; 'commandHandler.copiesGroupKey'?: boolean; 'commandHandler.archetypeGroupData'?: ObjectData; 'commandHandler.memberValidation'?: ((aGroup: Group, somePart: Part) => boolean) | null; 'commandHandler.defaultScale'?: number; 'commandHandler.zoomFactor'?: number; 'commandHandler.isZoomToFitRestoreEnabled'?: boolean; 'commandHandler.scrollToPartPause'?: number; 'grid.visible'?: boolean; 'grid.gridCellSize'?: Size; 'grid.gridOrigin'?: Point; 'toolManager.dragSize'?: Size; 'toolManager.gestureBehavior'?: GestureMode; 'toolManager.holdDelay'?: number; 'toolManager.hoverDelay'?: number; 'toolManager.mouseWheelBehavior'?: WheelMode; 'toolManager.currentToolTip'?: Adornment | HTMLInfo | null; 'toolManager.toolTipDuration'?: number; 'clickCreatingTool.archetypeNodeData'?: ObjectData | null; 'clickCreatingTool.isDoubleClick'?: boolean; 'clickCreatingTool.isGridSnapEnabled'?: boolean; 'contextMenuTool.defaultTouchContextMenu'?: Adornment | HTMLInfo | null; 'dragSelectingTool.box'?: Part; 'dragSelectingTool.delay'?: number; 'dragSelectingTool.isPartialInclusion'?: boolean; 'draggingTool.copiesEffectiveCollection'?: boolean; 'draggingTool.copyCursor'?: string; 'draggingTool.delay'?: number; 'draggingTool.dragOptions'?: DraggingOptions; 'draggingTool.dragsLink'?: boolean; 'draggingTool.dragsTree'?: boolean; 'draggingTool.gridSnapCellSize'?: Size; 'draggingTool.gridSnapCellSpot'?: Spot; 'draggingTool.gridSnapOrigin'?: Point; 'draggingTool.isComplexRoutingRealtime'?: boolean; 'draggingTool.isCopyEnabled'?: boolean; 'draggingTool.isGridSnapEnabled'?: boolean; 'draggingTool.isGridSnapRealtime'?: boolean; 'draggingTool.moveCursor'?: string; 'draggingTool.nodropCursor'?: string; 'linkReshapingTool.handleArchetype'?: GraphObject; 'linkReshapingTool.midHandleArchtype'?: GraphObject; 'linkReshapingTool.resegmentingDistance'?: number; 'linkingTool.archetypeLabelNodeData'?: ObjectData | null; 'linkingTool.archetypeLinkData'?: ObjectData | null; 'linkingTool.direction'?: LinkingDirection; 'linkingTool.isForwards'?: boolean; 'linkingTool.isUnconnectedLinkvalid'?: boolean; 'linkingTool.linkValidation'?: (fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean; 'linkingTool.linkingCursor'?: string; 'linkingTool.portGravity'?: number; 'linkingTool.portTargeted'?: (node: Node, port: GraphObject, tempNode: Node, tempPort: GraphObject, toEnd: boolean) => void; 'linkingTool.temporaryFromNode'?: Node; 'linkingTool.temporaryFromPort'?: GraphObject; 'linkingTool.temporaryLink'?: Link; 'linkingTool.temporaryToNode'?: Node; 'linkingTool.temporaryToPort'?: GraphObject; 'panningTool.bubbles'?: boolean; 'relinkingTool.fromHandleArchetype'?: GraphObject; 'relinkingTool.isForwards'?: boolean; 'relinkingTool.isUnconnectedLinkvalid'?: boolean; 'relinkingTool.linkValidation'?: (fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean; 'relinkingTool.linkingCursor'?: string; 'relinkingTool.portGravity'?: number; 'relinkingTool.portTargeted'?: (node: Node, port: GraphObject, tempNode: Node, tempPort: GraphObject, toEnd: boolean) => void; 'relinkingTool.temporaryFromNode'?: Node; 'relinkingTool.temporaryFromPort'?: GraphObject; 'relinkingTool.temporaryLink'?: Link; 'relinkingTool.temporaryToNode'?: Node; 'relinkingTool.temporaryToPort'?: GraphObject; 'relinkingTool.toHandleArchetype'?: GraphObject; 'resizingTool.cellSize'?: Size; 'resizingTool.dragsMembers'?: boolean; 'resizingTool.handleArchetype'?: GraphObject; 'resizingTool.isGridSnapEnabled'?: boolean; 'resizingTool.maxSize'?: Size; 'resizingTool.minSize'?: Size; 'rotatingTool.handleAngle'?: number; 'rotatingTool.handleArchetype'?: GraphObject; 'rotatingTool.handleDistance'?: number; 'rotatingTool.snapAngleEpsilon'?: number; 'rotatingTool.snapAngleMultiple'?: number; 'textEditingTool.defaultTextEditor'?: HTMLInfo; 'textEditingTool.selectsTextOnActivate'?: boolean; 'textEditingTool.starting'?: TextEditingStarting; 'textEditingTool.textValidation'?: (tb: TextBlock, oldString: string, newString: string) => boolean; 'undoManager.isEnabled'?: boolean; 'undoManager.maxHistoryLength'?: number; 'themeManager.defaultTheme'?: string; 'themeManager.currentTheme'?: string; 'themeManager.changesDivBackground'?: boolean; 'themeManager.themeMap'?: Map; } /** * This enumeration specifies how the Diagram should attempt to scale its {@link Diagram.documentBounds} into the view. * Used for {@link Diagram.autoScale}. * @since 3.0 */ export declare enum AutoScale { /** * The default auto scale type, does not attempt to scale. */ None = 1, /** * The whole {@link Diagram.documentBounds} are scaled uniformly to fit in the view. */ Uniform = 2, /** * The whole {@link Diagram.documentBounds} are scaled to fit in the view in one direction while a scrollbar is still needed in the other direction. */ UniformToFill = 3 } /** * This enumeration specifies how the Diagram should handle cycles in graphs. * Used for {@link Diagram.validCycle}. * @since 3.0 */ export declare enum CycleMode { /** * This value states that there are no restrictions on making cycles of links. */ All = 1, /** * This value states that a valid link from a node will not produce a directed cycle in the graph. */ NotDirected = 2, /** * This value states that a valid link from a node will not produce an undirected cycle in the graph. */ NotUndirected = 4, /** * This value states that any number of destination links may go out of a node, but at most one * source link may come into a node, and there are no directed cycles. * * This value assumes that the graph does not already have any cycles in it, * or else the behavior may be indeterminate. */ DestinationTree = 5, /** * This value states that any number of source links may come into a node, but at most one * destination link may go out of a node, and there are no directed cycles. * * This value assumes that the graph does not already have any cycles in it, * or else the behavior may be indeterminate. */ SourceTree = 6 } /** * This enumeration specifices how a Diagram can be scrolled. * Used for {@link Diagram.scrollMode}. * @since 3.0 */ export declare enum ScrollMode { /** * This value states that the viewport constrains scrolling to the Diagram document bounds. */ Document = 1, /** * This value states that the viewport does not constrain scrolling to the Diagram document bounds. */ Infinite = 2 } /** * (undocumented) * This enumeration specifies how the Diagram should handle tree collapsing. * Used for {@link Diagram.treeCollapsePolicy}. * @since 3.0 */ export declare enum CollapsePolicy { /** * This value states that only the {@link Node.findTreeParentNode}'s * {@link Node.isTreeExpanded} property determines whether a "child" node is visible. */ TreeParent = 1, /** * This value states that if all of the {@link Node.findNodesInto} or {@link Node.findNodesOutOf}, * ignoring Links that are not {@link Link.isTreeLink}, * depending on {@link isTreePathToChildren} being true or false, * are not {@link Node.isTreeExpanded}, the "child" node will be not visible. */ AllParents = 2, /** * This value states that if any of the {@link Node.findNodesInto} or {@link Node.findNodesOutOf}, * ignoring Links that are not {@link Link.isTreeLink}, * depending on {@link isTreePathToChildren} being true or false, * is not {@link Node.isTreeExpanded}, the "child" node will be not visible. */ AnyParents = 3 } /** * A Diagram is associated with an HTML DIV element. Constructing a Diagram creates * an HTML Canvas element which it places inside of the given DIV element, in addition to several helper DIVs. * **GoJS** will manage the contents of this DIV -- you should not modify the contents of the DIV, * although you may style the given DIV (background, border, etc) and position and size it as needed. * * Minimal Diagram construction looks like this. HTML: * ```html *
* ``` * * JavaScript: * ```js * * const myDiagram = * new go.Diagram("myDiagramDiv", // create a Diagram for the Div HTML element * { // with various property and subproperty settings... * "undoManager.isEnabled": true // enable undo & redo * }); * ``` * * The diagram will draw onto an HTML Canvas element, created inside the Diagram DIV. * * Each Diagram holds a set of {@link Layer}s each of which holds some number of {@link Part}s * such as {@link Node}s and {@link Link}s. * Each {@link Part} consists of {@link GraphObject}s such as {@link TextBlock}s and {@link Shape}s * and {@link Panel}s holding yet more GraphObjects. * * A Diagram and its Parts provide the visual representation of a {@link Model} that holds JavaScript * data objects for the nodes and the links. * The model provides the way to recognize the relationships between the data. *

* Two Diagrams can display and manipulate the same Model. (Example) * * A diagram will automatically create {@link Node}s and {@link Link}s corresponding to the model data. * The diagram has a number of named templates it uses to create the actual parts: * {@link nodeTemplateMap}, {@link groupTemplateMap}, and {@link linkTemplateMap}. * Each template may have some data {@link Binding}s that set the part's {@link GraphObject}s' properties * based on the value of properties of the data. * * A simple Node template and Model data (both nodes and links) may look like this: * * ```js * // define a simple Node template * myDiagram.nodeTemplate = * new go.Node("Auto").add( // the Shape will go around the TextBlock * new go.Shape("RoundedRectangle") * // Shape.fill is bound to Node.data.color * .bind("fill", "color"), * new go.TextBlock({ margin: 3 }) // some room around the text * // TextBlock.text is bound to Node.data.key * .bind("text", "key") * ); * * // create the model data that will be represented by Nodes and Links * myDiagram.model = new go.GraphLinksModel( * [ * { key: "Alpha", color: "lightblue" }, * { key: "Beta", color: "orange" }, * { key: "Gamma", color: "lightgreen" }, * { key: "Delta", color: "pink" } * ], * [ * { from: "Alpha", to: "Beta" }, * { from: "Alpha", to: "Gamma" }, * { from: "Beta", to: "Beta" }, * { from: "Gamma", to: "Delta" }, * { from: "Delta", to: "Alpha" } * ]); * ``` *

* The above code is used to make the Minimal sample, a simple example of * creating a Diagram and setting its model. *

* Read about models on the Using Models page in the introduction. * A diagram is responsible for scrolling ({@link position}) and zooming ({@link scale}) all of the parts that it shows. * Each {@link Part} occupies some area given by its {@link GraphObject.actualBounds}. * * The union of all of the parts' bounds constitutes the {@link documentBounds}. * The document bounds determines the area that the diagram can be scrolled to. * There are several properties that you can set, such as {@link initialContentAlignment}, * that control the initial size and position of the diagram contents. * * At any later time you can also explicitly set the {@link position} and/or {@link scale} to * get the appearance that you want. But you may find it easier to call methods to get the desired effect. * For example, if you want to make a particular Node be centered in the viewport, * call either {@link centerRect} or {@link scrollToRect} with the Node's {@link GraphObject.actualBounds}, * depending on whether or not you want the view to be scrolled if the node is already in view. *

* Read in the Introduction about Viewports * and the Initial Viewport. * You can have the diagram perform automatic layouts of its nodes and links by setting * {@link layout} to an instance of the {@link Layout} subclass of your choice. * The default {@link layout} is an instance of the {@link Layout} base class that ignores links and * only positions {@link Node}s that do not have a location. * This default layout will allow you to programmatically position nodes (including by loading * from a database) and will also allow the user to manually position nodes using the {@link DraggingTool}. * * If you do supply a particular layout as the {@link layout}, you can control which {@link Part}s it operates * on by setting {@link Part.isLayoutPositioned}. * Normally, of course, it works on all top-level nodes and links. * The layout is performed both after the model is first loaded as well as after any part is added or removed * or changes visibility or size. * You can disable the initial layout by setting {@link Layout.isInitial} to false. * You can disable later automatic layouts by setting {@link Layout.isOngoing} to false. *

* See the Layouts page in the Introduction for a summary of layout behavior. * * A diagram maintains a collection of selected parts, the {@link Diagram.selection}. * To select a Part you set its {@link Part.isSelected} property to true. * * There are many properties, named "allow...", that control what operations the user * may perform on the parts in the diagram. These correspond to the same named * properties on {@link Layer} that govern the behavior for those parts in a particular layer. * Furthermore for some of these properties there are corresponding properties on * {@link Part}, named "...able", that govern the behavior for that individual part. * For example, the {@link allowCopy} property corresponds to {@link Layer.allowCopy} and * to the property {@link Part.copyable}. * The {@link Part.canCopy} predicate is false if any of these properties is false. *

* See the Permissions page for a more thorough discussion. * * The {@link commandHandler} implements various standard commands, * such as the {@link CommandHandler.deleteSelection} method and the * {@link CommandHandler.canDeleteSelection} predicate. *

* See the Commands page for a listing of keyboard commands and * the use of commands in general. * * The diagram supports modular behavior for mouse events by implementing "tools". * All mouse and keyboard events are represented by {@link InputEvent}s and redirected * to the {@link currentTool}. * The default tool is an instance of {@link ToolManager} which keeps three lists of mode-less tools: * {@link ToolManager.mouseDownTools}, {@link ToolManager.mouseMoveTools}, and {@link ToolManager.mouseUpTools}. * The ToolManager searches these lists when a mouse event happens to find the first tool that can run. * It then makes that tool the new {@link currentTool}, where it can continue to process input events. * When the tool is done, it stops itself, causing the {@link defaultTool} to be the new {@link currentTool}. * * Mouse-down tools include: * - {@link ToolManager.actionTool}, to support objects like "buttons" * - {@link ToolManager.relinkingTool}, to reconnect an existing link * - {@link ToolManager.linkReshapingTool}, to modify the route of an existing link * - {@link ToolManager.rotatingTool}, to change the angle of an object * - {@link ToolManager.resizingTool}, to change the size of an object * * Mouse-move tools include: * - {@link ToolManager.linkingTool}, to draw a new link * - {@link ToolManager.draggingTool}, to move or copy the selection * - {@link ToolManager.dragSelectingTool}, to select parts within a rectangular area * - {@link ToolManager.panningTool}, to pan the diagram * * Mouse-up tools include: * - {@link ToolManager.contextMenuTool}, to manage context menus * - {@link ToolManager.textEditingTool}, to support in-place text editing * - {@link ToolManager.clickCreatingTool}, to create new parts where the user clicks * - {@link ToolManager.clickSelectingTool}, to select parts * * You can also run a tool in a modal fashion by explicitly setting {@link currentTool}. * That tool will keep running until some code replaces the {@link currentTool}. * This normally happens when the current tool calls {@link Tool.stopTool}, such as on a mouse-up event. *

* See the Tools page for a listing of predefined tools and how they operate. * * A diagram raises various {@link DiagramEvent}s when interesting things happen that may have affected the whole diagram. * See the documentation for {@link DiagramEvent} for a complete listing. * * When you need to display multiple Models, but not at the same time, you can do so by using only one Diagram and setting the {@link model} to a different one. * You can also have two Diagrams share a DIV by swapping the {@link div} to `null` on one Diagram and setting it on the other. * When permanently removing a Diagram,t o clear any memory used, * set the {@link div} to `null` and remove all references to the Diagram. These scenarios are discussed more on the * Replacing Diagrams and Models intro page. * @category Diagram */ export class Diagram { /** * Construct an empty Diagram for a particular DIV HTML element. * * You will normally initialize properties of the Diagram that control its appearance and behavior. * These properties include: * - templates (such as {@link nodeTemplate} or {@link linkSelectionAdornmentTemplate}), * - an automatic layout (if desired, {@link layout}), * - positioning or scaling (such as {@link initialContentAlignment} or {@link initialAutoScale}), * - permissions (such as {@link isReadOnly} or {@link allowDelete}), or * - Tool or CommandHandler customization (such as {@link CommandHandler.archetypeGroupData} or * {@link Tool.isEnabled}): `diagram.toolManager.dragSelectingTool.isEnabled = false;`. * * Then you will need to construct a Model (usually a {@link GraphLinksModel}) for the Diagram, * initialize its data by setting its {@link Model.nodeDataArray} and other properties, * and then set the diagram's {@link model}. * * Finally, if you want to disassociate the Diagram from the HTML Div element, set {@link Diagram.div} to null. * If you remove a part of the HTML DOM containing a Div with a Diagram, you will need to * set {@link div} to null in order for the page to recover the memory. * * Unlike GraphObject, the Diagram constructor passes its init options to {@link GraphObject.make}. * This allows you to quickly set sub-properties when initializing a Diagram, such as setting properties * on the Diagram's {@link undoManager} or {@link commandHandler}. For example: * * ```js * const myDiagram = new go.Diagram("myDiagramDiv", * { * allowZoom: false, * "animationManager.isEnabled": false, // turn off automatic animations * "grid.visible": true, // display a background grid for the whole diagram * "grid.gridCellSize": new go.Size(20, 20), * // allow double-click in background to create a new node * "clickCreatingTool.archetypeNodeData": { text: "Node" }, * // allow Ctrl-G to call the groupSelection command * "commandHandler.archetypeGroupData": * { text: "Group", isGroup: true, color: "blue" }, * "commandHandler.copiesTree": true, // for the copy command * "commandHandler.deletesTree": true, // for the delete command * "toolManager.hoverDelay": 100, // how quickly tooltips are shown * // mouse wheel zooms instead of scrolls * "toolManager.mouseWheelBehavior": go.WheelMode.Zoom, * "draggingTool.dragsTree": true, // dragging for both move and copy * "draggingTool.isGridSnapEnabled": true, * layout: new go.TreeLayout( * { angle: 90, sorting: go.TreeLayout.SortingAscending }), * "undoManager.isEnabled": true, // enable undo & redo * // a Changed listener on the Diagram.model * "ModelChanged": e => { if (e.isTransactionFinished) saveModel(); } * }); * ``` * @param div - A reference to a DIV HTML element or its ID as a string. * If no DIV is supplied, a Diagram will be created in memory. The Diagram's {@link Diagram.div} property * can then be set later on. * @param init - A JavaScript object specifying optional initialization properties object. * Can specify Diagram properties, Diagram sub-properties such as `"undoManager.isEnabled": true`, * and DiagramEvent listeners. Example: * ```js * { * allowZoom: false, * "animationManager.isEnabled": false, * "ModelChanged": e => { if (e.isTransactionFinished) saveModel(); } * } * ``` */ constructor(div?: Element | string, init?: DiagramInitOptions); /** * * @param init - A JavaScript object specifying optional initialization properties object. * Can specify Diagram properties, Diagram sub-properties such as `"undoManager.isEnabled": true`, * and DiagramEvent listeners. Example: * ```js * { * allowZoom: false, * "animationManager.isEnabled": false, * "ModelChanged": e => { if (e.isTransactionFinished) saveModel(); } * } * ``` */ constructor(init?: DiagramInitOptions); /** * Gets or sets the rendering context type. Values are `'default'`, which uses the HTML Canvas, * or `'svg'`, which builds and updates an SVG DOM. * * Setting this value dynamically is uncommon, typically a render is chosen only once, * when the Diagram is initially created. Using the SVG rendering context is also uncommon, * because the default canvas context has considerably greater performance. * * For more information, see the intro page on the * SVG drawing context. * * @since 2.3 */ get renderer(): 'default' | 'svg' | 'canvas'; set renderer(value: 'default' | 'svg' | 'canvas'); /** * This static function returns `true` if GoJS detects a DOM. * In browser environments this is expected to be `true`, in Node-like environments, `false`. * Specifically, this will be `false` if there is no root `document` in the JavaScript context, * or if the DOM was disabled explicitly by calling {@link Diagram.useDOM}. * * Incomplete or mock implementations of a DOM may make this return true when * it is more appropriate that it returns false. If that is the case, set it to false by calling * {@link Diagram.useDOM}. * @since 2.2 */ static isUsingDOM(): boolean; /** * This static function sets whether or not GoJS should use a DOM, if one exists. * This can be set to `false` to simulate a DOM-less environment. * It is uncommon to set this, but may be required in some testing environments. * @param value * @since 2.2 */ static useDOM(value: boolean): void; /** * Removes all Parts from the Diagram, including unbound Parts except for the background grid, * and also clears out the {@link Model} and {@link UndoManager} and clipboard. * This operation is not undoable. * * Alternative actions are to replace the {@link model} with a new {@link Model} * (probably a {@link GraphLinksModel} or a {@link TreeModel}), * or to set {@link Model.nodeDataArray} with an empty JavaScript Array * (and {@link GraphLinksModel.linkDataArray}). * * This does not remove any listeners from the diagram. */ clear(): void; /** * (undocumented) * Call {@link clear} and also restore the templates, layers, layout and various Diagram properties to their original state. * @virtual */ reset(): void; /** * @virtual * (undocumented) * Used in Diagram constructor setup, this computes the pixel width of the scrollbars * @param elem */ setRTL(elem?: HTMLElement): void; /** * (undocumented) * Computes the pixel width of the scrollbars * @virtual * @param elem */ setScrollWidth(elem?: HTMLElement): void; /** * This static function gets the {@link Diagram} that is attached to an HTML DIV element. * @param div * @returns null if there is no {@link Diagram} associated with the given DIV, * or if the argument is not a DIV element nor a string naming such a DIV element in the HTML document. */ static fromDiv(div: Element | string): Diagram | null; /** * Gets or sets the Diagram's HTMLDivElement, via an HTML Element ID. * This is typically set automatically when a Div is supplied as an argument to Diagram's constructor. * * Setting this property to a new value will clobber any HTML and * inner DOM elements inside of both the new and the old divs. * It will then populate the Div with the elements * (inner Divs, Canvases) needed for the Diagram to function. * * If you want to disassociate the Diagram from the HTML Div element, set {@link Diagram.div} to null. * If you remove a part of the HTML DOM containing a Div with a Diagram, you will need to * set {@link div} to null in order for the page to recover the memory. * * You should not attempt to manually modify the contents of this Div. * Changing this property value does not raise a Changed event. */ get div(): HTMLDivElement | null; set div(value: HTMLDivElement | null); /** * (undocumented), but may be useful for change detection calls in Angular. * @virtual */ addEventListener(DOMElement: Element | Window | Document, name: string, listener: any, capture: boolean): void; /** * (undocumented), but may be useful for change detection calls in Angular. * @virtual */ removeEventListener(DOMElement: Element | Window | Document, name: string, listener: any, capture: boolean): void; /** * (undocumented) * Computes the device pixel ratio divided by the backing store pixel ratio * Used to set this._pixelRatio to a value other than 1. * @virtual */ computePixelRatio(): number; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doMouseDown(): void; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doMouseMove(): void; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doMouseUp(): void; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doMouseWheel(): void; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doKeyDown(): void; /** * (undocumented) * Call this method on the currentTool. * @virtual */ doKeyUp(): void; /** * (undocumented) * Focus the Diagram's canvas, allowing it to receive keyboard events. * This is called upon activation of mouseDown or mouseMove tools, or on any mouseUp. * * This is normally implemented as a simple call to {@link focus}. * Override this if you do not wish to focus the canvas under certain circumstances. * However the method should call {@link focus} most of the time in order to get the normal behaviors. * * {@link lastInput} can be used to inspect the mouseDown event that calls this method. * @virtual */ doFocus(): void; /** * Explicitly bring HTML focus to the Diagram's canvas. * This is called by tools that may create other HTML elements such as TextEditingTool. * * If {@link scrollsPageOnFocus} is false, this tries to keep the page at the same scroll position * that it had before calling {@link focus}. * This method is not overridable. */ focus(): void; /** * This is called during a Diagram update to determine a new value for {@link documentBounds}. * By default this computes the union of the bounds of all the visible * {@link GraphObject}s in this Diagram, unless {@link Diagram.fixedBounds} is set. * This ignores parts for which {@link Part.isVisible} is false and * ignores those for which {@link Part.isInDocumentBounds} is false. * The returned value includes the addition of the {@link padding} margin. * * To compute the bounds of a collection of Parts, call {@link computePartsBounds}. * @virtual * @param rect - An optional Rect to modify and return, instead of returning a new Rect * @returns a Rect in document coordinates. If the argument rect was specified, it returns that modified rect. */ protected computeBounds(rect?: Rect): Rect; /** * Find the union of the {@link GraphObject.actualBounds} of all of the {@link Part}s in the given collection, * excluding Links unless the second argument is true. * * Unlike {@link computeBounds}, this ignores the visibility of each Part and does not add any padding to the result. * @virtual * @param coll - an iterable collection or Array of {@link Part}s. * @param includeLinks - defaults to false * @returns This returns the bounding area of the given Parts; * if there are no Parts in the collection, this returns a Rect with zero width and height and an X and Y that are NaN. */ computePartsBounds(coll: Iterable | Array, includeLinks?: boolean): Rect; /** * Scales the Diagram to uniformly fit into the viewport. To have this done automatically, * set the Diagram's {@link autoScale} to {@link AutoScale.Uniform}. * * The scale will not be increased past the value of {@link defaultScale}, which is normally 1.0, * so as to prevent a single node from appearing to fill up the whole viewport. * * To Animate zoomToFit, use {@link CommandHandler.zoomToFit}. * @see {@link CommandHandler.zoomToFit} */ zoomToFit(): void; /** * Modifies the {@link scale} and {@link position} of the Diagram * so that the viewport displays a given document-coordinates rectangle. * @param r - rectangular bounds in document coordinates. * @param scaling - an optional value of either {@link AutoScale.Uniform} (the default) or {@link AutoScale.UniformToFill}. */ zoomToRect(r: Rect, scaling?: AutoScale): void; /** * Aligns the Diagram's {@link position} based on a desired document {@link Spot} and viewport {@link Spot}. * @param documentspot * @param viewportspot */ alignDocument(documentspot: Spot, viewportspot: Spot): void; /** * (undocumented) * Sets the GraphObject on which to focus the viewport. * @param obj * @since 2.1 */ focusObject(obj: GraphObject | null): void; /** * This convenience function finds the front-most {@link Part} * that is at a given point that might be selectable and that is not in a temporary layer. * * This just calls {@link findObjectAt} with appropriate arguments, * but ignoring Layers that are {@link Layer.isTemporary}. * @param p - a Point in document coordinates. * @param selectable - Whether to only consider parts that are {@link Part.selectable}. The default is true. * @see {@link findObjectAt} * @see {@link findObjectsAt} * @see {@link findObjectsIn} * @see {@link findObjectsNear} * @see {@link findPartsAt} * @see {@link findPartsIn} * @see {@link findPartsNear} */ findPartAt(p: Point, selectable?: boolean): Part | null; /** * Find the front-most {@link GraphObject} at the given point in document coordinates. * * If {@link Layer.visible} is false, this method will not find any objects in that layer. * However, {@link Layer.opacity} does not affect this method. * * Example usage: * ```js * // Returns the top-most object that is a selectable Part, or null if there isn't one * myDiagram.findObjectAt( * myDiagram.lastInput.documentPoint, * // Navigation function * x => x.part, * // Because of the navigation function, x will always be a Part. * x => x.canSelect() * ); * ``` * @param p - A Point in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @returns The first GraphObject returned by the *navig* function * and satisfying the *pred* function that is at the point *p*, in Z-order from front to back, * or else null if nothing is found. * @see {@link findObjectsAt} * @see {@link findObjectsIn} * @see {@link findObjectsNear} * @see {@link findPartAt} */ findObjectAt(p: Point, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null): (T | null); /** * This convenience function finds all {@link Part}s that are at a point in document coordinates * and that are not in temporary layers. * * @param p - A Point in document coordinates. * @param selectable - Whether to only consider parts that are {@link Part.selectable}. The default is true. * @param coll - An optional collection (List or Set) to add the results to. * @see {@link findPartAt} * @see {@link findPartsIn} * @see {@link findPartsNear} * @see {@link findObjectsAt} * @since 2.0 */ findPartsAt | Set = Set>(p: Point, selectable?: boolean, coll?: S): S; /** * Return a collection of the {@link GraphObject}s at the given point in document coordinates. * * If {@link Layer.visible} is false, this method will not find any objects in that layer. * However, {@link Layer.opacity} does not affect this method. * * Example usage: * ```js * // Returns the Nodes that are at a given point, overlapping each other * myDiagram.findObjectsAt(somePoint, * // Navigation function -- only return Nodes * x => { const p = x.part; return (p instanceof go.Node) ? p : null; } * ); * ``` * @param p - A Point in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects returned by the *navig* function * and satisfying the *pred* that are located at the point *p*, or else an empty collection. * If a List or Set was passed in, it is returned. * @see {@link findObjectAt} * @see {@link findObjectsIn} * @see {@link findObjectsNear} * @see {@link findPartsAt} */ findObjectsAt | Set = Set>(p: Point, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, coll?: S): S; /** * This convenience function finds {@link Part}s that are inside or that intersect * a given {@link Rect} in document coordinates. * * This just calls {@link findObjectsIn} with appropriate arguments, * but ignoring Layers that are {@link Layer.isTemporary}. * @param r - a Rect in document coordinates. * @param partialInclusion - Whether a Part can match if it merely intersects the rectangular area (true) or * if it must be entirely inside the rectangular area (false). The default value is false. * @param selectable - Whether to only consider parts that are {@link Part.selectable}. The default is true. * @param coll - An optional collection (List or Set) to add the results to. * @see {@link findPartAt} * @see {@link findPartsAt} * @see {@link findPartsNear} * @see {@link findObjectsIn} * @since 2.0 */ findPartsIn | Set = Set>(r: Rect, partialInclusion?: boolean, selectable?: boolean, coll?: S): S; /** * Returns a collection of all {@link GraphObject}s that are inside or that intersect * a given {@link Rect} in document coordinates. * * If {@link Layer.visible} is false, this method will not find any objects in that layer. * However, {@link Layer.opacity} does not affect this method. * * Example usage: * ```js * // Returns the Links that intersect a given rectangle and have a certain data property * myDiagram.findObjectsIn(someRect, * // Navigation function -- only return Links * x => { const p = x.part; return (p instanceof go.Link) ? p : null; }, * // Predicate that always receives a Link, due to above navigation function * link => link.data.someProp > 17, * // the links may only partly overlap the given rectangle * true * ); * ``` * @param r - A Rect in document coordinates. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param partialInclusion - Whether an object can match if it merely intersects the rectangular area (true) or * if it must be entirely inside the rectangular area (false). The default value is false. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects returned by the *navig* function * and satisfying the *pred* function that are within the rectangle *r*, or else an empty collection. * If a List or Set was passed in, it is returned. * @see {@link findObjectAt} * @see {@link findObjectsAt} * @see {@link findObjectsNear} * @see {@link findPartsIn} */ findObjectsIn | Set = Set>(r: Rect, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, partialInclusion?: boolean, coll?: S): S; /** * This convenience function finds {@link Part}s that are within a certain distance * of a given point in document coordinates. * * This just calls {@link findObjectsNear} with appropriate arguments, * but ignoring Layers that are {@link Layer.isTemporary}. * @param p - A Point in document coordinates. * @param dist - The distance from the point. * @param partialInclusion - Whether an object can match if it merely intersects the circular area (true) or * if it must be entirely inside the circular area (false). The default is true. * @param selectable - Whether to only consider parts that are {@link Part.selectable}. The default is true. * @param coll - An optional collection (List or Set) to add the results to. * @see {@link findPartAt} * @see {@link findPartsAt} * @see {@link findPartsIn} * @see {@link findObjectsNear} * @since 2.0 */ findPartsNear | Set = Set>(p: Point, dist: number, partialInclusion?: boolean, selectable?: boolean, coll?: S): S; /** * Returns a collection of all {@link GraphObject}s that are within a certain distance * of a given point in document coordinates. * * If {@link Layer.visible} is false, this method will not find any objects in that layer. * However, {@link Layer.opacity} does not affect this method. * * Example usage: * ```js * // Returns the Nodes that intersect a given circular area and have a certain data property * myDiagram.findObjectsNear(somePoint, * // The circular area is centered at somePoint and has radius 100 * 100, * // Navigation function -- only return Nodes * x => { const p = x.part; return (p instanceof go.Node) ? p : null; }, * // Predicate that always receives a Node, due to above navigation function * node => node.data.someProp > 17, * // the nodes may only partly overlap the given circular area * true * ); * ``` * @param p - A Point in document coordinates. * @param dist - The distance from the point. * @param navig - A function taking a GraphObject and * returning a GraphObject, defaulting to the identity. * If this function returns null, the given GraphObject will not be included in the results. * @param pred - A function taking the GraphObject * returned by navig and returning true if that object should be returned, * defaulting to a predicate that always returns true. * @param partialInclusion - Whether an object can match if it merely intersects the circular area (true) or * if it must be entirely inside the circular area (false). The default value is true. * The default is true. * @param coll - An optional collection (List or Set) to add the results to. * @returns a collection of GraphObjects returned by the *navig* function * and satisfying the *pred* that are located near the point *p*, or else an empty collection. * If a List or Set was passed in, it is returned. * @see {@link findObjectAt} * @see {@link findObjectsAt} * @see {@link findObjectsIn} * @see {@link findPartsNear} */ findObjectsNear | Set = Set>(p: Point, dist: number, navig?: ((a: GraphObject) => (T | null)) | null, pred?: ((a: T) => boolean) | null, partialInclusion?: boolean | S, coll?: S): S; /** * (undocumented) * Requests that the Diagram updates its {@link documentBounds} in the near-future. */ invalidateDocumentBounds(): void; /** * (undocumented) * Invalidates all non-layout diagram state and forces an immediate redraw. * Because this can be very inefficient, to discourage its use it remains an undocumented part of the API. * @virtual */ redraw(): void; /** * Updates the diagram immediately, then resets initialization flags so that * actions taken in the argument function will be considered part of Diagram initialization, * and will participate in initial layouts, {@link initialAutoScale}, {@link initialContentAlignment}, etc. * * This is useful in situations where you do not wish for the first content added to the diagram to be considered * the "initial" content, such as with a Node that represents a "Loading" bar. * @param func - an optional function of actions to perform as part of another diagram initialization. */ delayInitialization(func?: ((diag: Diagram) => void) | null): void; /** * Usage of this method is uncommon and may affect performance, * for efficiency do not call this method unless you have a well-defined need. * Normally, GoJS updates the diagram automatically, and completeing a transaction ensures an immediate update. * * The most common reason to call this method when the HTML Div has changed size but the window has not changed size, * and the Diagram needs to be notified of this DOM change. See an example of resizing diagrams * here. * * Requests that in the near-future the diagram makes sure all GraphObjects are arranged, * recomputes the document bounds, updates the scrollbars, and redraws the viewport. * * @param alwaysQueueUpdate - If true the Diagram will queue another update, * even if an update is already occurring. The default value is false. * Side effects in an "InitialLayoutCompleted" DiagramEvent listener might necessitate setting this parameter. */ requestUpdate(alwaysQueueUpdate?: boolean): void; /** * (undocumented) * The use of this method at the wrong time may have some unexpected side-effects. */ maybeUpdate(): void; /** * (undocumented) * Get value of a given rendering hint. * @param name */ getRenderingHint(name: string): any; /** * (undocumented) * Set a rendering hint and draw immediately. * @param name * @param val */ setRenderingHint(name: string, val: any): void; /** * (undocumented) * Get value of a given input option * @param name */ getInputOption(name: string): any; /** * (undocumented) * Set value of a given input option * @param name * @param val */ setInputOption(name: string, val: any): void; /** * Set any number of properties on this Diagram. This is common in initialization. * This method can only be used to set existing properties on this object. To attach new properties, * or to set properties of sub-objects such as the {@link Diagram.toolManager}, {@link Diagram.animationManager}, * or {@link Diagram.commandHandler}, use {@link Diagram.attach}. * * This method uses TypeScript compile-time type checking, but does no runtime type checking. * * * @since 2.2 * @param config * @returns this Diagram * @see {@link setProperties} */ set(config: Partial): this; /** * This method sets a collection of properties according to the property/value pairs that have been set on the given Object, * in the same manner as {@link GraphObject.make} does when constructing a Diagram with an argument that is a simple JavaScript Object. * * This method does not use TypeScript compile-time type checking like {@link Diagram.set} does, * but is considerably more flexible in allowing you to set sub-properties and {@link DiagramEvent}s by quoted string names. * * You can set properties on an object that is the value of a property of the Diagram, * or on the {@link Diagram.toolManager}, {@link Diagram.animationManager}, or {@link Diagram.commandHandler} * by using a `"subpropname.property"` syntax for the property name. * At the current time only a single dot is permitted in the property "name". * * The property name may also be the name of a {@link DiagramEvent}, in which case this calls {@link addDiagramListener} with that DiagramEvent name. * ```js * aDiagram.attach({ * allowDelete: false, * "animationManager.isEnabled": false, // turn off automatic animations * // specify a group membership validation predicate * "commandHandler.memberValidation": (group, part) => ..., * "commandHandler.copiesTree": true, // for the copy command * // mouse wheel zooms instead of scrolls * "toolManager.mouseWheelBehavior": go.WheelMode.Zoom, * "draggingTool.dragsTree": true, // dragging for both move and copy * "draggingTool.isGridSnapEnabled": true, * layout: new go.TreeLayout(), * // add a DiagramEvent listener * "ExternalObjectsDropped": e => { e.subject.each(part => { ... }); } * }); * ``` * @param props - a plain JavaScript object with various property values to be set on this Diagram or on a part of this Diagram. * @since 2.2 * @returns this Diagram * @see {@link setProperties} a synonym of this method * @see {@link set} a type-safe method to set a collection of properties */ attach(props: ObjectData): this; /** * This method sets a collection of properties according to the property/value pairs that have been set on the given Object, * in the same manner as {@link GraphObject.make} does when constructing a Diagram with an argument that is a simple JavaScript Object. * * This method does not use TypeScript compile-time type checking like {@link Diagram.set} does, * but is considerably more flexible in allowing you to set sub-properties and {@link DiagramEvent}s by quoted string names. * * You can set properties on an object that is the value of a property of the Diagram, * or on the {@link Diagram.toolManager}, {@link Diagram.animationManager}, or {@link Diagram.commandHandler} * by using a `"subpropname.property"` syntax for the property name. * At the current time only a single dot is permitted in the property "name". * * The property name may also be the name of a {@link DiagramEvent}, in which case this calls {@link addDiagramListener} with that DiagramEvent name. * ```js * aDiagram.attach({ * allowDelete: false, * "animationManager.isEnabled": false, // turn off automatic animations * // specify a group membership validation predicate * "commandHandler.memberValidation": (group, part) => return ..., * "commandHandler.copiesTree": true, // for the copy command * // mouse wheel zooms instead of scrolls * "toolManager.mouseWheelBehavior": go.WheelMode.Zoom, * "draggingTool.dragsTree": true, // dragging for both move and copy * "draggingTool.isGridSnapEnabled": true, * layout: new go.TreeLayout(), * // add a DiagramEvent listener * "ExternalObjectsDropped": e => e.subject.each(part => { ... }) * }); * ``` * @param props - a plain JavaScript object with various property values to be set on this Diagram or on a part of this Diagram. * @returns this Diagram * @see {@link attach} a synonym of this method * @see {@link set} a type-safe method to set a collection of properties */ setProperties(props: ObjectData): this; /** * Adds a {@link Part} to the {@link Layer} that matches the Part's {@link Part.layerName}, * or else the default layer, which is named with the empty string. * * Normally parts added to a diagram are top-level parts. * If you want nodes to be members of a {@link Group}, in addition to calling this method * call {@link Group.addMembers} or set each {@link Part.containingGroup}. * @param part * @see {@link remove} */ add(part: Part): void; /** * Removes a {@link Part} from its {@link Layer}, provided the Layer is in this Diagram. * Removing a {@link Node} will also remove any Links that are connected with it. * Removing a {@link Group} will also remove all of its members. * Removing a {@link Link} will also remove all of its label Nodes, if it has any. * @param part * @see {@link add} */ remove(part: Part): void; /** * This method removes from this Diagram all of the {@link Part}s in a collection. * Removing a {@link Node} will also remove any Links that are connected with it. * Removing a {@link Group} will also remove all of its members. * Removing a {@link Link} will also remove all of its label Nodes, if it has any. * * This does not perform a transaction nor does it raise a {@link DiagramEvent}. * Call {@link CommandHandler.deleteSelection}, which calls this method, * if you want to delete all selected Parts. * The {@link CommandHandler.deleteSelection} command may delete other Parts as well, depending on {@link CommandHandler.deletesTree}. * * At this time there is no "addParts" method -- just call {@link Diagram.add} on each Part. * @param coll - A {@link List} or {@link Set | go.Set} or {@link Iterator} or Array of {@link Part}s. * @param check - Whether to check {@link Part.canDelete} on each part; default value is false. */ removeParts(coll: Iterable | Array, check?: boolean): void; /** * Make a copy of a collection of {@link Part}s and return them in a {@link Map | go.Map} mapping each original Part to its copy. * It may optionally add them to a given {@link Diagram}. * Copying a {@link Group} will also copy its member Nodes and Links. * Copying a {@link Link} will also copy any label Nodes that it owns. * * This does not perform a transaction nor does it raise a {@link DiagramEvent}. * Call {@link CommandHandler.copySelection}, which calls this method, * if you want to copy all selected Parts into the clipboard. * The {@link CommandHandler.copySelection} command may also copy additional Parts as well, depending on {@link CommandHandler.copiesTree}. * @param coll - A {@link List} or a {@link Set | go.Set} or {@link Iterator} of {@link Part}s, or an Array of {@link Part}s. * @param diagram - The destination diagram; if null, the copied parts are not added to this diagram. * @param check - Whether to check {@link Part.canCopy} on each part. The default value is false. */ copyParts(coll: Iterable | Array, diagram: Diagram | null, check?: boolean): Map; /** * Move a collection of {@link Part}s in this Diagram by a given offset. * Moving a {@link Group} will also move its member Nodes and Links. * Moving with a zero X and a zero Y offset is potentially useful in order to snap Parts to the grid if {@link DraggingTool.isGridSnapEnabled} is true. * * This does not perform a transaction nor does it raise a {@link DiagramEvent}. * * @param coll - A {@link List} or a {@link Set | go.Set} or {@link Iterator} of {@link Part}s, or an Array of {@link Part}s, * or null to move all of the Parts in this Diagram. * @param offset - the amount to move each Part, in document coordinates. * @param check - Whether to check {@link Part.canMove} on each part. The default value is false. * @param dragOptions - Optional dragging options. By default this uses the settings from the Diagram's DraggingTool. */ moveParts(coll: Iterable | Array, offset: Point, check?: boolean, dragOptions?: DraggingOptions): void; /** * This method computes the new location for a {@link Node} or simple {@link Part}, * given a new desired location, * taking any grid-snapping into consideration, * any {@link Part.dragComputation} function, * and any {@link Part.minLocation} and {@link Part.maxLocation}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param n - the Node or simple Part that is being moved * @param newloc - the proposed new location * @param dragOptions - the dragging options * @param result - an optional Point that is modified and returned * @returns the possibly grid-snapped computed Point that is within the minimum and maximum permitted locations * @since 2.0 */ computeMove(n: Part, newloc: Point, dragOptions: DraggingOptions, result?: Point): Point; set draggedLink(value: Link | null); /** * Adds a new {@link Layer} to the list of layers. * If {@link Layer.isTemporary} is false, the layer is added after all existing non-temporary layers. * If {@link Layer.isTemporary} is true, the layer is added as the very last layer. * @param layer - The new Layer to add. It is an error if the Layer already belongs to a Diagram. * @see {@link addLayerBefore} * @see {@link addLayerAfter} * @see {@link removeLayer} * @see {@link findLayer} * @returns this Diagram */ addLayer(layer: Layer): this; /** * Adds a layer to the list of layers before a specified layer. * This method can also re-order layers. * @param layer - the new Layer to add or existing Layer to move in Z-order. * @param existingLayer - the other Layer in this Diagram which should come just after the new or moved layer. * @see {@link addLayer} * @see {@link addLayerAfter} * @see {@link removeLayer} * @returns this Diagram */ addLayerBefore(layer: Layer, existingLayer: Layer): this; /** * Adds a layer to the list of layers after a specified layer. * This method can also re-order layers. * @param layer - the new Layer to add or existing Layer to move in Z-order. * @param existingLayer - the other Layer in this Diagram which should come just before the new or moved layer. * @see {@link addLayer} * @see {@link addLayerBefore} * @see {@link removeLayer} * @returns this Diagram */ addLayerAfter(layer: Layer, existingLayer: Layer): this; /** * Removes the given layer from the list of layers. * * Removing a layer does not remove the Parts in the layer. Instead, those Parts are placed into the default layer. * To remove all Parts in a layer you can call {@link Diagram.removeParts} with {@link Layer.parts} as the argument. * * You cannot remove the default layer, the one named with the empty string. * @param layer * @see {@link addLayer} * @see {@link addLayerBefore} * @see {@link addLayerAfter} * @see {@link findLayer} */ removeLayer(layer: Layer): void; /** * Finds a layer with a given name. * @param name * @returns a Layer with the given name, or null if no such layer was found. * @see {@link addLayerBefore} * @see {@link addLayerAfter} * @see {@link removeLayer} */ findLayer(name: string): Layer | null; /** * Finds a router with a given name in the Diagram's {@link routers} list. * By default, the only router is "AvoidsNodes" * @param name * @returns a Router with the given name, or null if no such router was found. * @since 3.0 */ findRouter(name: string): Router | null; /** * Register an event handler on this Diagram's {@link Diagram.model} that is called when there is a {@link ChangedEvent} * on the {@link Model}, not in this diagram. * Be sure to call {@link removeModelChangedListener} when you are done with the diagram. * * This is convenient when the {@link Diagram.model} may be replaced. * Using this method to register a Model Changed listener is more convenient than calling {@link Model.addChangedListener} directly * because when this diagram's Model is replaced, one does not need to call {@link Model.removeChangedListener} on the old Model * and then {@link Model.addChangedListener} again on the new Model. * * You can establish Model Changed listeners when you create a Diagram. * The Diagram init options are passed to {@link GraphObject.make}, which accepts "ModelChanged" as a shorthand. * For example: * ```js * new go.Diagram("myDiagramDiv", * { * "ModelChanged": e => { if (e.isTransactionFinished) saveModel(e.model); } * // ... other Diagram properties * }) * ``` * * This is equivalent to: * * ```js * new go.Diagram("myDiagramDiv", * { * // ... Diagram properties * }) * .addModelChangedListener(e => { if (e.isTransactionFinished) saveModel(e.model); }) * ``` * * Do not add or remove Changed listeners during the execution of a Changed listener. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link removeModelChangedListener} * @returns this Diagram */ addModelChangedListener(listener: ChangedEventHandler): this; /** * Unregister a {@link ChangedEvent} handler from this Diagram's {@link Diagram.model}. * The function argument must be the same reference as was passed to {@link addChangedListener}. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link addModelChangedListener} */ removeModelChangedListener(listener: ChangedEventHandler): void; /** * Register an event handler that is called when there is a {@link ChangedEvent} because this Diagram * or one of its Parts has changed, but not because the Model or any model data has changed. * * It is unusual to listen for Diagram ChangedEvents -- * it is far more common to listen for specific {@link DiagramEvent}s by calling {@link addDiagramListener}, * or to listen for Model ChangedEvents (i.e. changes to the model) by calling {@link addModelChangedListener}. * * Do not add or remove Changed listeners during the execution of a Changed listener. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link removeChangedListener} * @returns this Diagram */ addChangedListener(listener: ChangedEventHandler): this; /** * Unregister a {@link ChangedEvent} handler. * The function argument must be the same reference as was passed to {@link addChangedListener}. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link addChangedListener} */ removeChangedListener(listener: ChangedEventHandler): void; /** * This read-only property returns the {@link AnimationManager} for this Diagram. */ get animationManager(): AnimationManager; /** * This read-only property returns the {@link UndoManager} for this Diagram, which actually belongs to the {@link model}. * * The default UndoManager has its {@link UndoManager.isEnabled} property set to false. * If you want users to undo and redo, you should set that property to true once you have initialized the Diagram or its Model. * * Note that the UndoManager might be shared with other Diagrams that are showing the same Model. * The UndoManager might also be shared with other Models too. */ get undoManager(): UndoManager; /** * Gets or sets whether ChangedEvents are not recorded by the UndoManager. * The initial and normal value is false. * WARNING: while this property is true do not perform any changes that cause any previous transactions * to become impossible to undo. * * While this property is true, changing the Diagram or any GraphObject does not call {@link UndoManager.handleChanged}. * Even when this property is true, * transactions (such as calls to {@link startTransaction}) and * undo/redo (such as calls to {@link CommandHandler.undo}) * are still delegated to the {@link undoManager}. * * You should set this to true only temporarily, and you should remember its previous value * before setting this to true. * When finishing the period for which you want the UndoManager to be disabled, * you should set this back to the remembered value it had before it was set to true. * * For more permanent disabling of the {@link UndoManager}, set {@link UndoManager.isEnabled} to false. * * Setting this property also sets {@link Model.skipsUndoManager} to the same value. * Setting this property does not notify about any changed event. */ get skipsUndoManager(): boolean; set skipsUndoManager(value: boolean); /** * (undocumented) * When set to true Diagram layouts will not get invalidated. * Used by some tools stop real-time layouts from occuring during their operation. */ get delaysLayout(): boolean; set delaysLayout(value: boolean); /** * Begin a transaction, where the changes are held by a {@link Transaction} object * in the {@link UndoManager}. * This just calls {@link UndoManager.startTransaction}. * @param tname - a descriptive name for the transaction. * @returns the value returned by {@link UndoManager.startTransaction}. * @see {@link commit} */ startTransaction(tname?: string): boolean; /** * Commit the changes of the current transaction. * This just calls {@link UndoManager.commitTransaction}. * @param tname - a descriptive name for the transaction. * @returns the value returned by {@link UndoManager.commitTransaction}. */ commitTransaction(tname?: string): boolean; /** * Rollback the current transaction, undoing any recorded changes. * This just calls {@link UndoManager.rollbackTransaction}. * @returns the value returned by {@link UndoManager.rollbackTransaction}. */ rollbackTransaction(): boolean; /** * Starts a new transaction, calls the provided function, and commits the transaction. * Code is called within a try-finally statement. * If the function does not return normally, this rolls back the transaction rather than committing it. * Example usage: * ```js * myDiagram.commit(d => d.remove(somePart), "Remove Part"); * ``` * Note: passing null as the second argument will temporarily set {@link Diagram.skipsUndoManager} to true. * It is commonplace to call this method with no second argument, which would commit a transaction with * a transaction name that is the empty string. * @param func - the function to call as the transaction body * @param tname - a descriptive name for the transaction, or null to temporarily set {@link skipsUndoManager} to true; * if no string transaction name is given, an empty string is used as the transaction name */ commit(func: (d: Diagram) => void, tname?: string | null): void; /** * Update all of the data-bound properties of {@link Node}s and {@link Link}s in this diagram, * without having to call {@link Model.setDataProperty}. * This copies/converts model data properties to set properties on {@link Part}s. * This method does not conduct a transaction, so you need to start and commit one yourself. * * It is better to call {@link Model.setDataProperty} to modify data properties, * because that will both record changes for undo/redo and will update all bindings * that make depend on that property. * Simply modifying the data and calling an "update..." method will not be able to record * the previous value(s) of properties in the model data to support undo. * * If you know which model data objects have been modified, * it will be more efficient to update only the {@link Part}s that need it * by calling {@link Panel.updateTargetBindings}. * * To update relationships between nodes, call {@link updateAllRelationshipsFromData}. * @param srcprop - An optional source data property name: * when provided, only evaluates those {@link Binding}s that use that particular property; * when not provided or when it is the empty string, all bindings are evaluated. * @see {@link updateAllRelationshipsFromData} */ updateAllTargetBindings(srcprop?: string): void; /** * Update all of the theme-bound properties of {@link Node}s and {@link Link}s in this diagram. * * This method does not conduct a transaction, so you need to start and commit one yourself. * Typically, this transaction should skip the UndoManager. * @since 3.0 */ updateAllThemeBindings(): void; /** * If this Diagram has a div set, update the div's background color with the given CSS color string. * @since 3.0 */ setDivBackground(color: string): void; /** * Add or remove any nodes or links according to additional or missing data objects in the model * and update all of the references to nodes, in case they had been modified in the model without * properly notifying the model by calling {@link Model.addNodeData} or * {@link GraphLinksModel.removeLinkData} or * {@link GraphLinksModel.setGroupKeyForNodeData} or * {@link GraphLinksModel.setToKeyForLinkData} or other similar methods. * This method does not conduct a transaction, so you need to start and commit one yourself. * * It is better to call {@link Model.addNodeData}, {@link Model.removeNodeData}, * {@link GraphLinksModel.addLinkData}, {@link GraphLinksModel.removeLinkData}, * {@link Model.setDataProperty}, and other model methods to add/remove/modify data, * because those methods will both record changes for undo/redo and will update all bindings * that make depend on that property. * Simply modifying the data and calling an "update..." method will not be able to record * the previous value(s) of properties in the model data to support undo. * * This only adds, removes, or updates the relationships between nodes and links, * to have them reflect what is now declared in the model data. * If you know which model data objects have been modified, * it will be more efficient to update only the {@link Part}s that need it * by calling {@link Part.updateRelationshipsFromData}. * * To update {@link GraphObject} properties that are data bound, call {@link updateAllTargetBindings}. * @see {@link updateAllTargetBindings} */ updateAllRelationshipsFromData(): void; /** * Deselect all selected {@link Part}s. * This removes all parts from the {@link selection} collection. * * This method raises the "ChangingSelection" and "ChangedSelection" {@link DiagramEvent}s. * @virtual * @param skipsEvents - if true, do not raise the {@link DiagramEvent}s "ChangingSelection" and "ChangedSelection"; if not supplied the value is assumed to be false. * @see {@link select} * @see {@link selectCollection} * @see {@link clearHighlighteds} */ clearSelection(skipsEvents?: boolean): void; /** * Make the given object the only selected object. * Afterwards the {@link selection} collection will have only the given part in it. * * This method raises the "ChangingSelection" and "ChangedSelection" {@link DiagramEvent}s. * @param part - a Part that is already in a layer of this Diagram. * If the value is null, this does nothing. * @see {@link selectCollection} * @see {@link clearSelection} * @see {@link highlight} */ select(part: Part | null): void; /** * Select all of the {@link Part}s supplied in the given collection, and deselect all other Parts. * * This method raises the "ChangingSelection" and "ChangedSelection" {@link DiagramEvent}s. * @param coll - a {@link List} or {@link Set | go.Set} or {@link Iterator} or Array, of {@link Part}s to be selected. * @see {@link select} * @see {@link clearSelection} * @see {@link highlightCollection} */ selectCollection(coll: Iterable | Array): void; /** * Remove highlights from all {@link Part}s. * This removes all parts from the {@link highlighteds} collection. * * Note that no predefined command or tool operates on the {@link highlighteds} collection, * and there is no predefined visual rendering when a part becomes {@link Part.isHighlighted}. * @virtual * @see {@link highlight} * @see {@link highlightCollection} * @see {@link Part.isHighlighted} * @see {@link clearSelection} */ clearHighlighteds(): void; /** * Make the given part the only highlighted part. * Afterwards the {@link highlighteds} collection will have only the given part in it. * * Note that no predefined command or tool operates on the {@link highlighteds} collection, * and there is no predefined visual rendering when a part becomes {@link Part.isHighlighted}. * @param part - a Part that is already in a layer of this Diagram. * If the value is null, this does nothing. * @see {@link Part.isHighlighted} * @see {@link highlightCollection} * @see {@link clearHighlighteds} * @see {@link select} */ highlight(part: Part | null): void; /** * Highlight all of the {@link Part}s supplied in the given collection, and unhighlight all other highlighted Parts. * * Note that no predefined command or tool operates on the {@link highlighteds} collection, * and there is no predefined visual rendering when a part becomes {@link Part.isHighlighted}. * @param coll - a {@link List} or {@link Set | go.Set} or {@link Iterator} or Array, of {@link Part}s to be highlighted. * @see {@link Part.isHighlighted} * @see {@link highlight} * @see {@link clearHighlighteds} * @see {@link selectCollection} */ highlightCollection(coll: Iterable | Array): void; /** * Scrolling function used by primarily by {@link commandHandler}'s {@link CommandHandler.doKeyDown}. * @param unit - A string representing the unit of the scroll operation. Can only be 'pixel', 'line', 'page', or 'document'. * @param dir - The direction of the scroll operation. Can only be 'up', 'down', 'left', or 'right'. * @param dist - An optional distance multiplier, for multiple pixels, lines, or pages. The default value is 1. * This argument is ignored when the unit is 'document'. * @see {@link scrollToRect} * @see {@link centerRect} */ scroll(unit: ('pixel' | 'line' | 'page' | 'document'), dir: ('up' | 'down' | 'left' | 'right'), dist?: number): void; /** * Modifies the {@link position} to show a given Rect of the Diagram by centering the * viewport on that Rect. Does nothing if the Rect is already entirely in view. * * See also {@link centerRect} * @param r * @see {@link centerRect} * @see {@link scroll} * @see {@link CommandHandler.scrollToPart} */ scrollToRect(r: Rect): void; /** * Modifies the {@link position} to show a given Rect of the Diagram by centering the * viewport on that Rect. * * If the rect is near the {@link documentBounds} and if the * {@link scrollMargin} is small, it might not be possible to scroll far enough to * actually put the Rect area in the center of the viewport. * @param r * @see {@link scrollToRect} * @see {@link scroll} */ centerRect(r: Rect): void; /** * Given a Point in document coordinates, return a new Point in viewport coordinates. * @param p * @returns The given Point converted into View coordinates. * @see {@link transformViewToDoc} * @see {@link GraphObject.getDocumentPoint} */ transformDocToView(p: Point): Point; /** * Given a point in viewport coordinates, return a new Point in document coordinates. * @param p * @returns The given point converted into Document coordinates. * @see {@link transformDocToView} * @see {@link GraphObject.getDocumentPoint} */ transformViewToDoc(p: Point): Point; /** * @deprecated See {@link AutoScale.None}. */ static readonly None = AutoScale.None; /** * @deprecated See {@link AutoScale.Uniform}. */ static readonly Uniform = AutoScale.Uniform; /** * @deprecated See {@link AutoScale.UniformToFill}. */ static readonly UniformToFill = AutoScale.UniformToFill; /** * @deprecated See {@link CycleMode.All}. */ static readonly CycleAll = CycleMode.All; /** * @deprecated See {@link CycleMode.NotDirected}. */ static readonly CycleNotDirected = CycleMode.NotDirected; /** * @deprecated See {@link CycleMode.NotUndirected}. */ static readonly CycleNotUndirected = CycleMode.NotUndirected; /** * @deprecated See {@link CycleMode.DestinationTree}. */ static readonly CycleDestinationTree = CycleMode.DestinationTree; /** * @deprecated See {@link CycleMode.SourceTree}. */ static readonly CycleSourceTree = CycleMode.SourceTree; /** * @deprecated See {@link ScrollMode.Document}. */ static readonly DocumentScroll = ScrollMode.Document; /** * @deprecated See {@link ScrollMode.Infinite}. */ static readonly InfiniteScroll = ScrollMode.Infinite; /** * Gets or sets the opacity for all parts in this diagram. * The value must be between 0.0 (fully transparent) and 1.0 (no additional transparency). * This value is multiplicative with any existing transparency, * for instance from a {@link Brush} or image transparency. * The default value is 1. * @since 2.1 * @see {@link Layer.opacity} * @see {@link GraphObject.opacity} */ get opacity(): number; set opacity(value: number); /** * Gets or sets what kinds of graphs this diagram allows the user to draw. * By default this property is {@link CycleMode.All} -- all kinds of cycles are permitted. * Common values include {@link CycleMode.DestinationTree} and {@link CycleMode.NotDirected}. */ get validCycle(): CycleMode; set validCycle(value: CycleMode); /** * This read-only property returns an iterator for this Diagram's Layers. * @see {@link addLayer} * @see {@link removeLayer} */ get layers(): Iterator; /** * Gets or sets whether the Diagram's {@link Diagram.model} is {@link Model.isReadOnly}. * @see {@link isReadOnly} * @see {@link isEnabled} */ get isModelReadOnly(): boolean; set isModelReadOnly(value: boolean); /** * Gets or sets whether the Diagram may be modified by the user, * while still allowing the user to scroll, zoom, and select. * The initial value is false. * @see {@link isModelReadOnly} * @see {@link isEnabled} */ get isReadOnly(): boolean; set isReadOnly(value: boolean); /** * Gets or sets whether the user may interact with the Diagram. * @see {@link isReadOnly} * @see {@link isModelReadOnly} */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * Gets or sets whether the user may copy to or paste parts from the internal clipboard. * This allows use of {@link CommandHandler.cutSelection}, * {@link CommandHandler.copySelection} and {@link CommandHandler.pasteSelection}. * The initial value is true. */ get allowClipboard(): boolean; set allowClipboard(value: boolean); /** * Gets or sets whether the user may copy objects. * The initial value is true. * @see {@link Part.copyable} * @see {@link Part.canCopy} * @see {@link Layer.allowCopy} */ get allowCopy(): boolean; set allowCopy(value: boolean); /** * Gets or sets whether the user may delete objects from the Diagram. * The initial value is true. * @see {@link Part.deletable} * @see {@link Part.canDelete} * @see {@link Layer.allowDelete} */ get allowDelete(): boolean; set allowDelete(value: boolean); /** * Gets or sets whether the user may start a drag-and-drop in this Diagram, * possibly dropping in a different element. * The initial value is false. */ get allowDragOut(): boolean; set allowDragOut(value: boolean); /** * Gets or sets whether the user may end a drag-and-drop operation in this Diagram. * This is typically set to true when a Diagram is used with a {@link Palette}. * * The initial value is true. */ get allowDrop(): boolean; set allowDrop(value: boolean); /** * Gets or sets whether the user may do in-place text editing. * The initial value is true. * @see {@link Part.textEditable} * @see {@link Part.canEdit} * @see {@link Layer.allowTextEdit} */ get allowTextEdit(): boolean; set allowTextEdit(value: boolean); /** * Gets or sets whether the user may group parts together. * The initial value is true. * @see {@link Part.groupable} * @see {@link Part.canGroup} * @see {@link Layer.allowGroup} */ get allowGroup(): boolean; set allowGroup(value: boolean); /** * Gets or sets whether the user may ungroup existing groups. * The initial value is true. * @see {@link Group.ungroupable} * @see {@link Group.canUngroup} * @see {@link Layer.allowUngroup} */ get allowUngroup(): boolean; set allowUngroup(value: boolean); /** * Gets or sets whether the user may add parts to the Diagram. * The initial value is true. */ get allowInsert(): boolean; set allowInsert(value: boolean); /** * Gets or sets whether the user may draw new links. * The initial value is true. * @see {@link Layer.allowLink} */ get allowLink(): boolean; set allowLink(value: boolean); /** * Gets or sets whether the user may reconnect existing links. * The initial value is true. * @see {@link Link.relinkableFrom} * @see {@link Link.relinkableTo} * @see {@link Link.canRelinkFrom} * @see {@link Link.canRelinkTo} * @see {@link Layer.allowRelink} */ get allowRelink(): boolean; set allowRelink(value: boolean); /** * Gets or sets whether the user may move objects. * The initial value is true. * @see {@link Part.movable} * @see {@link Part.canMove} * @see {@link Layer.allowMove} */ get allowMove(): boolean; set allowMove(value: boolean); /** * Gets or sets whether the user may reshape parts. * The initial value is true. * @see {@link Part.reshapable} * @see {@link Part.canReshape} * @see {@link Layer.allowReshape} */ get allowReshape(): boolean; set allowReshape(value: boolean); /** * Gets or sets whether the user may resize parts. * The initial value is true. * @see {@link Part.resizable} * @see {@link Part.canResize} * @see {@link Layer.allowResize} */ get allowResize(): boolean; set allowResize(value: boolean); /** * Gets or sets whether the user may rotate parts. * The initial value is true. * @see {@link Part.rotatable} * @see {@link Part.canRotate} * @see {@link Layer.allowRotate} */ get allowRotate(): boolean; set allowRotate(value: boolean); /** * Gets or sets whether the user may select objects. * The initial value is true. * @see {@link Part.selectable} * @see {@link Part.canSelect} * @see {@link Layer.allowSelect} */ get allowSelect(): boolean; set allowSelect(value: boolean); /** * Gets or sets whether the user may undo or redo any changes. * The initial value is true. */ get allowUndo(): boolean; set allowUndo(value: boolean); /** * Gets or sets whether the user may zoom into or out of the Diagram. * The initial value is true. */ get allowZoom(): boolean; set allowZoom(value: boolean); /** * Gets or sets whether the Diagram has a vertical Scrollbar. * * To enable or disable scrolling itself, use {@link allowHorizontalScroll} and {@link allowVerticalScroll}. * * Adding or removing a scrollbar modifies the diagram's viewport. * * The initial value is true. * @see {@link allowVerticalScroll} * @see {@link hasHorizontalScrollbar} */ get hasVerticalScrollbar(): boolean; set hasVerticalScrollbar(value: boolean); /** * Gets or sets whether the Diagram has a horizontal Scrollbar. * * To enable or disable scrolling itself, use {@link allowHorizontalScroll} and {@link allowVerticalScroll}. * * Adding or removing a scrollbar modifies the diagram's viewport. * * The initial value is true. * @see {@link allowHorizontalScroll} * @see {@link hasVerticalScrollbar} */ get hasHorizontalScrollbar(): boolean; set hasHorizontalScrollbar(value: boolean); /** * Gets or sets whether the user is allowed to use the horizontal scrollbar. * The initial value is true. * @see {@link hasHorizontalScrollbar} * @see {@link allowVerticalScroll} */ get allowHorizontalScroll(): boolean; set allowHorizontalScroll(value: boolean); /** * Gets or sets whether the user is allowed to use the vertical scrollbar. * The initial value is true. * @see {@link hasVerticalScrollbar} * @see {@link allowHorizontalScroll} */ get allowVerticalScroll(): boolean; set allowVerticalScroll(value: boolean); /** * Gets or sets the distance in screen pixels that the horizontal scrollbar will scroll * when scrolling by a line. * * The default value is 16. * @see {@link scrollVerticalLineChange} */ get scrollHorizontalLineChange(): number; set scrollHorizontalLineChange(value: number); /** * Gets or sets the distance in screen pixels that the vertical scrollbar will scroll * when scrolling by a line. * * The default value is 16. * @see {@link scrollHorizontalLineChange} */ get scrollVerticalLineChange(): number; set scrollVerticalLineChange(value: number); /** * Gets or sets the last {@link InputEvent} that occurred. * * This property is useful in tools and real-time operations for determining * where the mouse pointer was most recently located. * * Setting this property does not notify about any changed event. * @see {@link firstInput} */ get lastInput(): InputEvent; set lastInput(value: InputEvent); set previousInput(value: InputEvent); /** * Gets or sets the most recent mouse-down {@link InputEvent} that occurred. * * Setting this property does not notify about any changed event. * @see {@link lastInput} */ get firstInput(): InputEvent; set firstInput(value: InputEvent); /** * Gets or sets the current cursor for the Diagram, overriding the {@link defaultCursor}. * * Valid CSS cursors are accepted, * such as "auto", "default", "none", "context-menu", "help", "pointer", "progress", "wait", etc. * * It is possible to use custom cursors with the syntax "url(path_to_image), default". * A fallback (like default here) is necessary for a custom cursor to work. * * To read more about cursor syntax, go to: * CSS cursors (mozilla.org). * * If the specified cursor is not accepted by the platform, this property setter will try prepending * `-webkit-` and `-moz-` prefixes when assigning the "cursor" CSS style property. * * Setting this property does not notify about any changed event. * Setting this value to the empty string ('') returns the Diagram's cursor to the {@link defaultCursor}. * @see {@link defaultCursor} * @see {@link GraphObject.cursor} */ get currentCursor(): string; set currentCursor(value: string); /** * Gets or sets the cursor to be used for the Diagram * when no {@link GraphObject} specifies a different cursor. * * Valid CSS cursors are accepted, * such as "auto", "default", "none", "context-menu", "help", "pointer", "progress", "wait", etc. * * It is possible to use custom cursors with the syntax "url(path_to_image), default". * A fallback (like default here) is necessary for a custom cursor to work. * * To read more about cursor syntax, go to: * CSS cursors (mozilla.org). * The default value is "auto". * @see {@link currentCursor} * @see {@link GraphObject.cursor} */ get defaultCursor(): string; set defaultCursor(value: string); /** * Gets or sets the function to execute when the user single-primary-clicks * on the background of the Diagram. * This typically involves a mouse-down followed by a prompt mouse-up * at approximately the same position using the left (primary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on no object. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name "BackgroundSingleClicked". * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link doubleClick} * @see {@link contextClick} * @see {@link GraphObject.click} */ get click(): ((e: InputEvent) => void) | null; set click(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user double-primary-clicks * on the background of the Diagram. * This typically involves a mouse-down/up/down/up in rapid succession * at approximately the same position using the left (primary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on no object. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name "BackgroundDoubleClicked". * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link click} * @see {@link contextClick} * @see {@link GraphObject.doubleClick} */ get doubleClick(): ((e: InputEvent) => void) | null; set doubleClick(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user single-secondary-clicks * on the background of the Diagram. * This typically involves a mouse-down followed by a prompt mouse-up * at approximately the same position using the right (secondary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on no object. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name "BackgroundContextClicked". * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link click} * @see {@link doubleClick} * @see {@link GraphObject.contextClick} */ get contextClick(): ((e: InputEvent) => void) | null; set contextClick(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse (pointer) in * the background of the Diagram without holding down any buttons, * not over any {@link GraphObject}s. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * After calling this function the diagram will be updated immediately. * @see {@link mouseHover} * @see {@link GraphObject.mouseOver} */ get mouseOver(): ((e: InputEvent) => void) | null; set mouseOver(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user holds the mouse (pointer) stationary in * the background of the Diagram without holding down any buttons, * not over any {@link GraphObject}s. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link mouseOver} * @see {@link GraphObject.mouseHover} * @see {@link ToolManager.doMouseHover} */ get mouseHover(): ((e: InputEvent) => void) | null; set mouseHover(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user holds the mouse (pointer) stationary in * the background of the Diagram while holding down a button, * not over any {@link GraphObject}s. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link GraphObject.mouseHold} * @see {@link ToolManager.doMouseHover} */ get mouseHold(): ((e: InputEvent) => void) | null; set mouseHold(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user is dragging the selection in * the background of the Diagram during a {@link DraggingTool} drag-and-drop, * not over any {@link GraphObject}s. * * If this property value is a function, it is called with an {@link InputEvent}. * It is called within the transaction performed by the {@link DraggingTool}. * By default this property is null. * * Note that for a drag-and-drop that originates in a different diagram, the target diagram's * selection collection will not be the parts that are being dragged. * Instead the temporary parts being dragged can be found as the source diagram's {@link DraggingTool.copiedParts}. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * After calling this function the diagram will be updated immediately. * * For example, if you want to prevent the user from dropping Parts into the background of the diagram, * and want to provide feedback about that during a drag: * ```js * myDiagram.mouseDragOver = e => { * myDiagram.currentCursor = "no-drop"; * } * ``` * @see {@link mouseDrop} * @see {@link GraphObject.mouseDragEnter} * @see {@link GraphObject.mouseDragLeave} */ get mouseDragOver(): ((e: InputEvent) => void) | null; set mouseDragOver(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the user drops the selection in * the background of the Diagram at the end of a {@link DraggingTool} drag-and-drop, * not onto any {@link GraphObject}s. * * If this property value is a function, it is called with an {@link InputEvent}. * It is called within the transaction performed by the {@link DraggingTool}. * By default this property is null. * * For example, if you want to prevent the user from dropping Parts into the background of the diagram: * ```js * myDiagram.mouseDrop = e => { * myDiagram.currentTool.doCancel(); * } * ``` * @see {@link mouseDragOver} * @see {@link GraphObject.mouseDrop} */ get mouseDrop(): ((e: InputEvent) => void) | null; set mouseDrop(value: ((e: InputEvent) => void) | null); /** * Gets or sets whether drag-and-drop events may be bubbled up to the diagram if not handled by a part. * The default value is false -- each Node or Link that in the diagram needs to define * its own {@link GraphObject.mouseDragEnter}, {@link GraphObject.mouseDragLeave}, and {@link GraphObject.mouseDrop} * event handlers if you want dragging/dropping on a part to act as if the user were acting on the diagram. * * If set to true, this will call {@link Diagram.mouseDragOver} during a drag, even while dragging over top-level parts, * and {@link Diagram.mouseDrop} will be called even when dropping onto parts. * * This property will have no impact while dropping on a Group. * The Group's mouseDrop and {@link Group.handlesDragDropForMembers} should be set if desired. * * GraphObjects do not have a mouseDragOver property, so if this is set to true, the Diagram's mouseDragOver will * always be called, even when dragging over a part. * @see {@link mouseDragOver} * @see {@link mouseDrop} * @see {@link Group.handlesDragDropForMembers} * @see {@link GraphObject.mouseDrop} * @since 2.0 */ get handlesDragDropForTopLevelParts(): boolean; set handlesDragDropForTopLevelParts(value: boolean); /** * Gets or sets the function to execute when the mouse (pointer) enters the Diagram. * (When the browser's mouseEnter event fires on the Diagram canvas.) * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link mouseLeave} * @see {@link GraphObject.mouseEnter} * @since 2.0 */ get mouseEnter(): ((e: InputEvent) => void) | null; set mouseEnter(value: ((e: InputEvent) => void) | null); /** * Gets or sets the function to execute when the mouse (pointer) leaves the Diagram. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link startTransaction} and {@link commitTransaction}, * or call {@link commit}. * @see {@link mouseEnter} * @see {@link GraphObject.mouseLeave} * @since 2.0 */ get mouseLeave(): ((e: InputEvent) => void) | null; set mouseLeave(value: ((e: InputEvent) => void) | null); /** * This {@link Adornment} or {@link HTMLInfo} is shown when the mouse (pointer) stays motionless in the background. * The default value is null, which means no tooltip is shown. * * Here is a simple example: * ```js * diagram.toolTip = * new go.Adornment("Auto").add( * new go.Shape({ fill: "#CCFFCC" }), * new go.TextBlock("This diagram lets you control the world.", * { margin: 4 }) * ); * ``` * @see {@link GraphObject.toolTip} * @see {@link ToolManager.doToolTip} */ get toolTip(): Adornment | HTMLInfo | null; set toolTip(value: Adornment | HTMLInfo | null); /** * This {@link Adornment} or {@link HTMLInfo} is shown when the use context clicks in the background. * The default value is null, which means no context menu is shown. * On touch devices, a special default context menu will appear even there is no context menu defined. * See {@link ContextMenuTool.defaultTouchContextMenu} for details. * * ```js * diagram.contextMenu = * go.GraphObject.build("ContextMenu").add( * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => e.diagram.commandHandler.undo() }) * .add(new go.TextBlock("Undo")) * .bindObject("visible", "", o => o.diagram.commandHandler.canUndo()), * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => e.diagram.commandHandler.redo() }) * .add(new go.TextBlock("Redo")) * .bindObject("visible", "", o => o.diagram.commandHandler.canRedo()) * ); * ``` * @see {@link GraphObject.contextMenu} * @see {@link ContextMenuTool} */ get contextMenu(): Adornment | HTMLInfo | null; set contextMenu(value: Adornment | HTMLInfo | null); /** * Gets or sets the {@link CommandHandler} for this Diagram. * * This is set to a new instance of {@link CommandHandler} on Diagram instantiation. * * Setting this property does not notify about any changed event. * The value cannot be null and must not be shared with other Diagrams. */ get commandHandler(): CommandHandler; set commandHandler(value: CommandHandler); /** * Gets or sets the {@link ToolManager} for this Diagram. * This tool is used for mode-less operation. * It is responsible for choosing a particular tool to run as the {@link currentTool}. * * This tool is normally also the {@link defaultTool}. * If you don't want the ToolManager to run at all, * replace the {@link defaultTool} with your own tool. * * Setting this property does not notify about any changed event. * The value cannot be null and must not be shared with other Diagrams. * If you set this property, you will probably also want to set {@link defaultTool}. * @see {@link defaultTool} */ get toolManager(): ToolManager; set toolManager(value: ToolManager); /** * Gets or sets the default tool for this Diagram that becomes the current tool when the current tool stops. * Initially this value is the same tool as {@link toolManager}, which is an instance of {@link ToolManager}. * * Setting this property also sets the {@link currentTool} if the old default tool is the currently running tool. * * Setting this property does not notify about any changed event. * The value cannot be null and must not be shared with other Diagrams. * @see {@link currentTool} * @see {@link toolManager} */ get defaultTool(): Tool; set defaultTool(value: Tool); /** * Gets or sets the current tool for this Diagram that handles all input events. * This value is frequently replaced by the {@link toolManager} as different tools run. * * Each Diagram has a number of tools that define its behavior when responding to mouse events. * These include {@link ClickSelectingTool}, {@link DraggingTool}, {@link DragSelectingTool}, {@link LinkingTool}, and {@link ResizingTool}, among others. * * Initially this is set to the value of {@link defaultTool}. * Setting this to a null value is treated as if it were set to the {@link defaultTool}, * because there should always be a currently running tool, except when the diagram is being initialized. * * A {@link ToolManager} is the default tool used by a Diagram - it chooses to run one of the other tools * depending on the circumstances. * * Setting this property to a new tool stops the previous current tool * * Setting this property does not notify about any changed event. * @see {@link defaultTool} * @see {@link toolManager} */ get currentTool(): Tool; set currentTool(value: Tool | null); /** * This read-only property returns the read-only collection of selected objects. * Most commands and many tools operate on this collection. * * Do not modify this collection. * If you want to select or deselect a particular object in a Diagram, * set the {@link Part.isSelected} property. * If you want to select a collection of Parts, call {@link selectCollection}. * If you want to deselect all objects, call {@link clearSelection}. * If you want to deselect all objects and select a single object, call {@link select}. * * You can limit how many objects the user can select by setting {@link maxSelectionCount}. * * There are also {@link DiagramEvent}s for "ChangingSelection" and "ChangedSelection", * which are raised by commands and tools before and after changes to this selection collection. * * Note that selection collection and {@link Part.isSelected} property are completely independent * of the {@link highlighteds} collection and the {@link Part.isHighlighted} property. */ get selection(): Set; /** * Gets or sets the maximum number of selected objects. * The default value is a large positive integer. * Values must be non-negative. * Decreasing this value may cause objects to be removed from {@link selection} * in order to meet the new lower limit. */ get maxSelectionCount(): number; set maxSelectionCount(value: number); /** * Gets or sets the default selection {@link Adornment} template, used to adorn selected Parts other than Groups or Links. * * Each {@link Node} or simple {@link Part} can have its own {@link Part.selectionAdornmentTemplate}, * which if non-null will take precedence over this Diagram property. * * This Adornment must not be in the visual tree of any Diagram. * The value must not be null. */ get nodeSelectionAdornmentTemplate(): Adornment; set nodeSelectionAdornmentTemplate(value: Adornment); /** * Gets or sets the default selection {@link Adornment} template, used to adorn selected Groups. * * Each {@link Group} can have its own {@link Part.selectionAdornmentTemplate}, which if non-null will take precedence over this Diagram property. * * This Adornment must not be in the visual tree of any Diagram. * The value must not be null. */ get groupSelectionAdornmentTemplate(): Adornment; set groupSelectionAdornmentTemplate(value: Adornment); /** * Gets or sets the default selection {@link Adornment} template, used to adorn selected Links. * * Each {@link Link} can have its own {@link Part.selectionAdornmentTemplate}, which if non-null will take precedence over this Diagram property. * * This Adornment must not be in the visual tree of any Diagram. * The value must not be null. */ get linkSelectionAdornmentTemplate(): Adornment; set linkSelectionAdornmentTemplate(value: Adornment); /** * This read-only property returns the read-only collection of highlighted parts. * * Do not modify this collection. * If you want to highlight or remove the highlight for a particular Part in a Diagram, * set the {@link Part.isHighlighted} property. * If you want to highlight a collection of Parts, call {@link highlightCollection}. * If you want to remove all highlights and highlight a single object, call {@link highlight}. * If you want to remove all highlights, call {@link clearHighlighteds}. * * Note that highlighteds collection and {@link Part.isHighlighted} property are completely independent * of the {@link selection} collection and the {@link Part.isSelected} property. * No predefined command or tool operates on this highlighteds collection. */ get highlighteds(): Set; /** * Gets or sets whether this Diagram's state has been modified. * Setting this property does not notify about any changed event, * but it does raise the "Modified" {@link DiagramEvent}, * although perhaps not immediately. * * Returns true if the Diagram has been changed, * if the {@link undoManager} has recorded any changes, or * if an undo has been performed without a corresponding redo. * * Replacing the {@link model} automatically sets this property to false after the initial layout has completed. * The "Modified" DiagramEvent is also raised when an undo or a redo has finished. * A "Modified" DiagramEvent listener must not modify this Diagram or its Model. */ get isModified(): boolean; set isModified(value: boolean); /** * Gets or sets the {@link Model} holding data corresponding to the * data-bound nodes and links of this Diagram. * * Replacing this value causes all of the bound Nodes and Links to be deleted and re-created * from the new model data. * * Models may be shared by multiple Diagrams. One common approach is to have two * Diagrams displaying the same Model but using different templates * (see {@link nodeTemplate}, {@link nodeTemplateMap}, and the associated link and group properties) and sometimes even different Layouts. * * Setting this property does not notify about any changed event; the new value must not be null. * Typically a new Model will have its own {@link UndoManager}, thereby replacing the Diagram's * current UndoManager. * * Replacing or re-setting the model will re-initialize the Diagram, taking in to account * {@link initialPosition}, {@link initialScale}, {@link initialAutoScale}, and {@link initialContentAlignment}. * It will also set {@link isModified} to false. * * The default behavior when replacing the model is to copy a few {@link UndoManager} properties to the * new UndoManager, including {@link UndoManager.isEnabled} and {@link UndoManager.maxHistoryLength}. * * It is an error to replace the Diagram.model while a transaction is in progress. */ get model(): Model; set model(value: Model); /** * Gets or sets the {@link ThemeManager} for this Diagram. */ get themeManager(): ThemeManager; set themeManager(value: ThemeManager); /** * Gets or sets the license key. * Read more about the license key at Deployment. * @since 2.0 */ static get licenseKey(): string; static set licenseKey(value: string); /** * Gets the current GoJS version. * @since 2.0 */ static get version(): string; /** * Remove all of the {@link Part}s created from model data * and then create them again. * This must be called after modifying or replacing any of the template maps * such as {@link nodeTemplateMap}. * This re-selects all of the new Parts that were created from data of the original selected Parts. * * If you modify a template Map, there is no notification that the map has changed. * You will need to call rebuildParts explicitly. * If you are replacing the {@link nodeTemplate} or the {@link nodeTemplateMap} or * the corresponding properties for Groups or Links, * the Diagram property setters will automatically call rebuildParts. * * It is extremely wasteful to call this method after making some model data changes that you want to * be reflected in the diagram. Instead, it is better call {@link Model.setDataProperty}, * {@link Model.addNodeData}, {@link Model.removeNodeData}, or other model methods. * Not only do those methods update efficiently, they also preserve unbound state and support undo/redo. */ rebuildParts(): void; /** * Look for a {@link Part} or {@link Node} or {@link Group} corresponding to a model's data object's unique key. * This will find a {@link Link} if the model is a {@link GraphLinksModel} that is maintaining a key on the link data objects. * @param key - a string or number. * @returns null if a data with that key cannot be found in the model, * or if a corresponding {@link Part} cannot be found in the Diagram. * This will not return a {@link Link} unless the model is a {@link GraphLinksModel} and * {@link GraphLinksModel.linkKeyProperty} has been set. * If the same key is used for both a node data object and a link data object, this will return a Node. */ findPartForKey(key: Key): Part | null; /** * Look for a {@link Node} or {@link Group} corresponding to a model's node data object's unique key. * @param key - a string or number. * @returns null if a node data with that key cannot be found in the model, * or if a corresponding {@link Node} or {@link Group} cannot be found in the Diagram, * or if what is found is just a {@link Part}. */ findNodeForKey(key: Key): Node | null; /** * Look for a {@link Link} corresponding to a model's link data object's unique key. * @param key - a string or number. * @returns null if a link data with that key cannot be found in the model, * or if a corresponding {@link Link} cannot be found in the Diagram, * or if the model is a {@link GraphLinksModel} without {@link GraphLinksModel.linkKeyProperty} set to a non-empty string. * @since 2.1 */ findLinkForKey(key: Key): Link | null; /** * Look for a {@link Part}, {@link Node}, {@link Group}, or {@link Link} corresponding to a {@link Model}'s data object. * We recommend that you call {@link findNodeForData} or {@link findLinkForData} if you are looking for a {@link Node} or a {@link Link}. * @param data - a JavaScript object matched by reference identity * @returns an existing {@link Part} in this Diagram that was * created because its `Part.data` was the data in the Diagram's {@link Model}. */ findPartForData(data: ObjectData): Part | null; /** * Look for a {@link Node} or {@link Group} corresponding to a model's node data object. * @param nodedata - a JavaScript object matched by reference identity; * use {@link findNodesByExample} if you want to find those Nodes whose data matches an example data object * @returns an existing {@link Node} or {@link Group} in this Diagram that was * created because its `Part.data` was the node data in the Diagram's {@link Model}. * This will be null if there is no such part or if it's just a {@link Part} or {@link Link}. */ findNodeForData(nodedata: ObjectData): Node | null; /** * Look for a {@link Link} corresponding to a {@link GraphLinksModel}'s link data object. * @param linkdata - a JavaScript object matched by reference identity; * use {@link findLinksByExample} if you want to find those Links whose data matches an example data object * @returns an existing {@link Link} in this Diagram that was * created because its `Part.data` was the link data in the Diagram's {@link Model}. */ findLinkForData(linkdata: ObjectData): Link | null; /** * Search for Nodes or Groups by matching the Node data with example data holding values, RegExps, or predicates. * * For example, calling this method with an argument object: * `{ sex: "M", name: /^Alex/i, age: n => n >= 18 }` * will return an iterator of Nodes whose `Node.data` is a JavaScript object whose: * - sex is "M" (a case-sensitive string comparison), and * - name starts with the string "Alex" (using a case-insensitive match), and * - age is greater than or equal to 18 * * Here is how an example value can match the corresponding data value: * - A string, number, or boolean is compared with the === operator. * - A function is treated as a predicate and applied to the data value. * - A regular expression (RexExp) is matched against the toString() of the data value. * Common expressions include: * - `/abc/` matches any string that includes exactly the substring "abc" * - `/abc/i` matches any string that includes the substring "abc", but uses a case-insensitive comparison * - `/^no/i` matches any string that starts with "no", ignoring case * - `/ism$` matches any string that ends with "ism" exactly * - `/(green|red) apple/` matches any string that includes either "green apple" or "red apple" * * For more details read Regular Expressions (mozilla.org). * - An Array requires the data value to also be an Array of equal or greater length. * Each example array item that is not undefined is matched with the corresponding data array item. * - An Object is recursively matched with the data value, which must also be an Object. * * All properties given by the argument example data must be present on the node data, * unless the example property value is undefined. * All other data properties are ignored when matching. * * When multiple argument objects are given, if any of the objects match the node's data, * the node is included in the results. * @param examples - one or more JavaScript Objects whose properties are either predicates to be * applied or RegExps to be tested or values to be compared to the corresponding data property value * @see {@link findLinksByExample} */ findNodesByExample(...examples: Array): Iterator; /** * Search for Links by matching the Link data with example data holding values, RegExps, or predicates. * * See the documentation of {@link findNodesByExample} for how the example * data can match data of bound Parts. * @param examples - one or more JavaScript Objects whose properties are either predicates to be * applied or RegExps to be tested or values to be compared to the corresponding data property value * @see {@link findNodesByExample} */ findLinksByExample(...examples: Array): Iterator; /** * Gets or sets the default {@link Node} template used as the archetype * for node data that is added to the {@link model}. * Setting this property just modifies the {@link nodeTemplateMap} * by replacing the entry named with the empty string. * * The value must not be null. * The template may be either a {@link Node} or a simple {@link Part}, * but not a {@link Link} or a {@link Group}. * * This Part must not be in the visual tree of any Diagram. */ get nodeTemplate(): Part; set nodeTemplate(value: Part); /** * Gets or sets a {@link Map | go.Map} mapping template names to {@link Part}s. * These nodes are copied for each node data that is added to the {@link model}. * * The new value must not be null and must contain {@link Node}s or simple {@link Part}s. * These Parts must not be in the visual tree of any Diagram. * Replacing this Map will automatically call {@link rebuildParts}. * * If you modify this {@link Map | go.Map}, by replacing a {@link Node} or by adding or * removing a map entry, you need to explicitly call {@link rebuildParts} afterwards. * Any new map values must not be {@link Link}s or {@link Group}s. * * If you want to create {@link Group}s, use {@link groupTemplateMap} instead. */ get nodeTemplateMap(): Map; set nodeTemplateMap(value: Map); /** * Gets or sets the default {@link Group} template used as the archetype * for group data that is added to the {@link model}. * * Setting this property just modifies the {@link groupTemplateMap} * by replacing the entry named with the empty string. * The value must not be null and must be a {@link Group}, not a {@link Node} or simple {@link Part}. * This Part must not be in the visual tree of any Diagram. */ get groupTemplate(): Group; set groupTemplate(value: Group); /** * Gets or sets a {@link Map | go.Map} mapping template names to {@link Group}s. * These groups are copied for each group data that is added to the {@link model}. * * The new value must not be null, nor may it contain a {@link Node} or {@link Link} or simple {@link Part}. * The Links must not be in the visual tree of any Diagram. * Replacing this Map will automatically call {@link rebuildParts}. * * If you modify this {@link Map | go.Map}, by replacing a {@link Group} in it or by adding or * removing a map entry, you need to explicitly call {@link rebuildParts} afterwards. */ get groupTemplateMap(): Map; set groupTemplateMap(value: Map); /** * Gets or sets the default {@link Link} template used as the archetype * for link data that is added to the {@link model}. * * Setting this property just modifies the {@link linkTemplateMap} * by replacing the entry named with the empty string. * The value must not be null and must be a {@link Link}, not a {@link Node} or simple {@link Part}. * This Link must not be in the visual tree of any Diagram. */ get linkTemplate(): Link; set linkTemplate(value: Link); /** * Gets or sets a {@link Map | go.Map} mapping template names to {@link Link}s. * These links are copied for each link data that is added to the {@link model}. * * The new value must not be null and must contain only {@link Link}s, not {@link Node}s or simple {@link Part}s. * The Links must not be in the visual tree of any Diagram. * Replacing this Map will automatically call {@link rebuildParts}. * * If you modify this {@link Map | go.Map}, by replacing a {@link Link} in it or by adding or * removing a map entry, you need to explicitly call {@link rebuildParts} afterwards. */ get linkTemplateMap(): Map; set linkTemplateMap(value: Map); /** * Gets or sets whether mouse events initiated within the Diagram will be captured. * The initial value is true. * Setting this property does not notify about any changed event. */ get isMouseCaptured(): boolean; set isMouseCaptured(value: boolean); /** * Gets or sets the coordinates of this Diagram in the viewport. * Value must be of type {@link Point} in document coordinates. * The default is Point(NaN, NaN), but is typically set to a real value when a Diagram is initialized. * * Scrolling and panning the Diagram modify the Diagram's position. * * Setting this property does not notify about any changed event. * However you can listen with {@link addDiagramListener} for a {@link DiagramEvent} * with the name "ViewportBoundsChanged". * * The {@link viewportBounds} x and y values are always the same as the Diagram's position values. * * If you set this property any replacement of the {@link model} will result in a layout * and a computation of new {@link documentBounds}, which in turn may cause the diagram to be scrolled * and zoomed, depending on various Diagram properties named "initial...". * You may want to set {@link initialPosition} instead of setting this property around the time * that you are loading a model. */ get position(): Point; set position(value: Point); /** * Gets or sets the initial coordinates of this Diagram in the viewport, eventually setting the {@link position}. * This value is relevant on initialization of a {@link model} or if {@link delayInitialization} is called. * Value must be of type Point in document coordinates. * The default is Point(NaN, NaN). * * Setting this property has the same effect as implementing * an "InitialLayoutCompleted" DiagramEvent listener that sets {@link position}. * * Setting this property does not notify about any changed event. * @see {@link initialDocumentSpot} * @see {@link initialViewportSpot} */ get initialPosition(): Point; set initialPosition(value: Point); /** * Gets or sets the initial scale of this Diagram in the viewport, eventually setting the {@link scale}. * This value is relevant on initialization of a {@link model} or if {@link delayInitialization} is called. * The default is NaN. * * Setting this property has the same effect as implementing * an "InitialLayoutCompleted" DiagramEvent listener that sets {@link scale}. */ get initialScale(): number; set initialScale(value: number); /** * Gets or sets a {@link Panel} of type {@link Panel.Grid} acting as the background grid * extending across the whole viewport of this diagram. */ get grid(): Panel; set grid(value: Panel); /** * This read-only property returns the bounds of the portion of the Diagram in document coordinates that is viewable from its HTML Canvas. * Typically when the viewport bounds are smaller than the {@link documentBounds}, the user can scroll or pan the view. * * The x and y coordinates are equal to the {@link position} of the Diagram, * and the width and height are equal to the Diagram's canvas width and height, * divided by the {@link scale}. */ get viewportBounds(): Rect; /** * Gets or sets a fixed size in document coordinates to be returned by {@link viewportBounds}. This is typically only set when the Diagram's {@link div} is `null`. * This property is intended to be used in DOM-less environments where there is no Diagram {@link div} expected, to simulate the size of the DIV. * Normally, the {@link viewportBounds} is sized by the DIV instead. * * By default this is `Size(NaN, NaN)`. * If this property is set, its size will always be used to compute the {@link viewportBounds}, even if * a {@link div} is also set. It is uncommon to set both this property and a Diagram DIV. * * See the intro page on GoJS within Node.js for a usage example. * * @see {@link viewportBounds} * @since 2.0 */ get viewSize(): Size; set viewSize(value: Size); /** * Gets or sets a fixed bounding rectangle to be returned by {@link documentBounds} * and {@link computeBounds}. * By default this has NaN values, meaning that {@link computeBounds} * will compute the union of all of the parts in the Diagram to determine the {@link documentBounds}. * If all x/y/width/height values are real numbers, this value is used as the {@link documentBounds}. */ get fixedBounds(): Rect; set fixedBounds(value: Rect); /** * Gets or sets a scrollable area in document coordinates that surrounds the document bounds, allowing the user to scroll into empty space. * * The margin is only effective in each direction when the document bounds plus margin is greater than the viewport bounds. * * The default value is a margin of 0, all around the edge of the document. */ get scrollMargin(): MarginLike; set scrollMargin(value: MarginLike); /** * Gets or sets the scrollMode of the Diagram, allowing the user to either * scroll to document bound borders with {@link ScrollMode.Document}, * or scroll endlessly with {@link ScrollMode.Infinite}. * * The default value is {@link ScrollMode.Document}. * Changing this property value does not raise a Changed event. */ get scrollMode(): ScrollMode; set scrollMode(value: ScrollMode); /** * Gets or sets whether the page may be scrolled when the diagram receives focus. * This happens in some browsers when the top-left corner of the diagram's HTMLDivElement * is scrolled out of view, the diagram does not have focus, and the user clicks in the diagram. * * The default value is false. */ get scrollsPageOnFocus(): boolean; set scrollsPageOnFocus(value: boolean); /** * Gets or sets the function used to determine the position that this Diagram can be scrolled or moved to. * * By default this function is null and the Diagram's position is bound only by the document bounds. * * When this property is set the function is given a reference to the diagram and the proposed new position Point. * The function must return a new point. * * An example that disallows decimal position values: * ```js * function computeIntegralPosition(diagram, pt) { * return new go.Point(Math.floor(pt.x), Math.floor(pt.y)); * } * ``` * * The function, if supplied, must not have any side-effects. */ get positionComputation(): ((thisDiagram: Diagram, newPosition: Point) => Point) | null; set positionComputation(value: ((thisDiagram: Diagram, newPosition: Point) => Point) | null); /** * Gets or sets the function used to determine valid scale values for this Diagram. */ get scaleComputation(): ((thisDiagram: Diagram, newScale: number) => number) | null; set scaleComputation(value: ((thisDiagram: Diagram, newScale: number) => number) | null); /** * This read-only property returns the bounds of the diagram's contents, in document coordinates. * * This is normally computed and set by {@link computeBounds} during Diagram updates * that can occur for any number of relevant reasons, such as a {@link Part} changing size. * * The Diagram's documentBounds can have an unvarying specific value * by setting the {@link fixedBounds} property. * * If the documentBounds are larger than the {@link viewportBounds}, * scrollbars will appear on desktop browsers. You can disable scrolling with the * {@link allowHorizontalScroll} and {@link allowVerticalScroll} properties, and * you can disable scrollbars themselves with the {@link hasHorizontalScrollbar} * and {@link hasVerticalScrollbar} properties. */ get documentBounds(): Rect; /** * Ensures that the {@link documentBounds} are up to date. * This is sometimes necessary when operations need updated document bounds immediately. * * It is uncommon to call this method outside of customization. * For efficiency, do not call this method unnecessarily. * @since 2.1.30 * @see {@link Part.ensureBounds} */ ensureBounds(): void; /** * (undocumented) */ get isVirtualized(): boolean; set isVirtualized(value: boolean); /** * Gets or sets the scale transform of this Diagram. * Value must be a positive number. * The default value is 1. * Any new value will be coerced to be between {@link minScale} and {@link maxScale}. * * Scale can automatically be set by the {@link autoScale} property. * There are also {@link initialScale} and {@link initialAutoScale} for * setting the scale on (re)initialization of a Diagram. * * Setting this property does not notify about any changed event. * However you can listen with {@link addDiagramListener} for a {@link DiagramEvent} * with the name "ViewportBoundsChanged". * * If you set this property any replacement of the {@link model} will result in a layout * and a computation of new {@link documentBounds}, which in turn may cause the diagram to be scrolled * and zoomed, depending on various Diagram properties named "initial...". * You may want to set {@link initialScale} instead of setting this property around the time * that you are loading a model. */ get scale(): number; set scale(value: number); /** * Gets or sets the {@link Diagram.scale} set by {@link CommandHandler.resetZoom} * and when computing stretch values, such as when {@link autoScale} or * {@link initialAutoScale} are set, or when {@link zoomToFit} is called. * * The default value is 1.0. * The value must be a number larger than 0. * Setting this property does not raise any events. * @since 2.0 */ get defaultScale(): number; set defaultScale(value: number); /** * Gets or sets the autoScale behavior of the Diagram, controlling whether or not the * Diagram's bounds automatically scale to fit the view. * * The only accepted values are the constant properties of Diagram, * {@link AutoScale.None}, {@link AutoScale.Uniform}, or {@link AutoScale.UniformToFill}. * Setting this will change the Diagram's {@link Diagram.scale} and {@link Diagram.position}, if appropriate. * * The default value is {@link AutoScale.None} - the scale and position are not automatically adjusted * according to the area covered by the document. * When the value is not None, any value for {@link initialAutoScale} or {@link initialScale} is ignored. *

* When autoScale is set to a non-{@link AutoScale.None} value, * the user will not be able to zoom, and setting {@link scale} will do nothing. * If you only want to scale automatically on initialization, use {@link initialAutoScale}. * * Setting this property to {@link AutoScale.Uniform} is basically the same as calling {@link zoomToFit} * all the time, or just disabling interactive zooming. * * Note that depending on the values of {@link maxScale} and {@link minScale}, the actual value for {@link scale} * might be limited. * * The scale will not be increased past the value of {@link defaultScale}, which is normally 1.0, * so as to prevent a single node from appearing to fill up the whole viewport. * * @see {@link initialAutoScale} */ get autoScale(): AutoScale; set autoScale(value: AutoScale); /** * Gets or sets how the scale of the diagram is automatically * set at the time of the "InitialLayoutCompleted" DiagramEvent, after the model has been replaced. * * The only accepted values are listed as constant properties of Diagram, * such as {@link AutoScale.None}, {@link AutoScale.Uniform}, or {@link AutoScale.UniformToFill}. * Setting this will change the Diagram's {@link Diagram.scale} and {@link Diagram.position}, if appropriate. * * If you want to always automatically scale the Diagram, set {@link autoScale} instead. * If you want to set the scale to a specific value on initialization (each time the model is replaced), * set {@link initialScale}. * * The default value is {@link AutoScale.None} -- the scale and position are not automatically adjusted * according to the area covered by the document. * * Setting this property to {@link AutoScale.Uniform} is basically the same as calling {@link zoomToFit} * in an "InitialLayoutCompleted" {@link DiagramEvent} listener. * * Note that depending on the values of {@link maxScale} and {@link minScale}, the actual value for {@link scale} * might be limited. * * Setting this property to {@link AutoScale.Uniform} is basically the same as calling {@link zoomToFit} * all the time, or just disabling interactive zooming. * * Note that depending on the values of {@link maxScale} and {@link minScale}, the actual value for {@link scale} * might be limited. * * The scale will not be increased past the value of {@link defaultScale}, which is normally 1.0, * so as to prevent a single node from appearing to fill up the whole viewport. * * @see {@link autoScale} */ get initialAutoScale(): AutoScale; set initialAutoScale(value: AutoScale); /** * Gets or sets the spot in the viewport that should be coincident with the * {@link initialDocumentSpot} of the document when the document is first initialized. * The default value is {@link Spot.None}. * * If you set this, often you will also want to set {@link initialDocumentSpot}. * If you set {@link initialPosition}, it will take precedence over this property. * * Setting this property and {@link initialDocumentSpot} has the same effect as implementing * an "InitialLayoutCompleted" DiagramEvent listener that calls {@link alignDocument}. * * @see {@link initialDocumentSpot} * @see {@link initialContentAlignment} */ get initialViewportSpot(): Spot; set initialViewportSpot(value: Spot); /** * Gets or sets the spot in the document's area that should be coincident with the * {@link initialViewportSpot} of the viewport when the document is first initialized. * The default value is {@link Spot.None}. * * If you set this, often you will also want to set {@link initialViewportSpot}. * If you set {@link initialPosition}, it will take precedence over this property. * * Setting this property and {@link initialViewportSpot} has the same effect as implementing * an "InitialLayoutCompleted" DiagramEvent listener that calls {@link alignDocument}. * * @see {@link initialViewportSpot} * @see {@link initialPosition} * @see {@link initialContentAlignment} */ get initialDocumentSpot(): Spot; set initialDocumentSpot(value: Spot); /** * Gets or sets the smallest value greater than zero that {@link scale} may take. * This property is only used to limit the range of new values of {@link scale}. * * The default value is 0.0001. * Values must be larger than zero and not greater than one. * Setting this to a value that is greater than the current {@link scale} * will cause the current diagram scale to be set to this new value. */ get minScale(): number; set minScale(value: number); /** * Gets or sets the largest value that {@link scale} may take. * This property is only used to limit the range of new values of {@link scale}. * * The default value is 100.0. * Values must be no less than one. * Setting this to a value that is less than the current {@link scale} * will cause the current diagram scale to be set to this new value. */ get maxScale(): number; set maxScale(value: number); /** * Gets or sets the zoom point of this Diagram, in viewport coordinates. * This is used by {@link Tool.standardMouseWheel} and scale-setting commands to control where to zoom in or out. * * Typical usage is to remember the value of this property and * to set this property to some point within the viewport (between zero and the canvas width and height). * This is commonly accomplished by using the {@link InputEvent.viewPoint} of {@link Diagram.lastInput}. * Then one changes the {@link scale} somehow, perhaps by executing one of the {@link CommandHandler} commands, * or by rotating the mouse wheel, or just by setting the {@link Diagram.scale} property. * Finally one restores the original value of this property. * * The default value is Point(NaN, NaN). * Value must be of type {@link Point}, in element coordinates, not in document coordinates. * Setting this property does not notify about any changed event. */ get zoomPoint(): Point; set zoomPoint(value: Point); /** * Gets or sets the content alignment {@link Spot} of this Diagram, to be used in determining * how parts are positioned when the {@link viewportBounds} width or height is larger than the {@link documentBounds}. * * For instance a spot of {@link Spot.Center} would ensure that the Diagram's * contents are always centered in the viewport. * * If you want the content to be aligned only initially, use {@link initialContentAlignment} instead. * * The default value is {@link Spot.Default}, which causes no automatic scrolling or positioning. * When the value is not Default, any value for {@link initialContentAlignment} or {@link initialPosition} is ignored. * * Setting this property has the same effect as implementing * a "LayoutCompleted" DiagramEvent listener that scrolls the viewport to align the content. * */ get contentAlignment(): Spot; set contentAlignment(value: Spot); /** * Gets or sets the initial content alignment {@link Spot} of this Diagram, to be used in determining * how parts are positioned initially relative to the viewport, when the {@link viewportBounds} width or height is larger than the {@link documentBounds}. * * For instance a spot of {@link Spot.Center} would ensure that the Diagram's contents are initially centered in the viewport. * * To initially align the document when the documentBounds are larger than the viewport, use {@link initialDocumentSpot} and {@link initialViewportSpot}. * * If you want the content to be constantly aligned with a spot, use {@link contentAlignment} instead. * * The default value is {@link Spot.Default}, which causes no automatic scrolling or positioning. * * Setting this property has the same effect as implementing * an "InitialLayoutCompleted" DiagramEvent listener that scrolls the viewport to align the content. * * @see {@link initialDocumentSpot} * @see {@link initialViewportSpot} */ get initialContentAlignment(): Spot; set initialContentAlignment(value: Spot); /** * Gets or sets the Margin that describes the Diagram's padding, * which controls how much extra space in document coordinates there is around the area occupied by the document. * This keeps nodes from butting up against the side of the diagram (unless scrolled). * * The default value is a margin of 5, all around the edge of the document. */ get padding(): MarginLike; set padding(value: MarginLike); /** * This read-only property returns an iterator of all {@link Node}s and {@link Group}s in the Diagram. * * This includes both data-bound and unbound nodes, * and both top-level nodes and nodes inside {@link Group}s. * All of the simple {@link Part}s are accessible via the {@link parts} property. * @see {@link findTopLevelGroups} * @see {@link findTreeRoots} */ get nodes(): Iterator; /** * This read-only property returns an iterator of all {@link Link}s in the Diagram. * * This includes both data-bound and unbound links, * and both top-level links and links inside {@link Group}s. */ get links(): Iterator; /** * This read-only property returns an iterator of all {@link Part}s in the Diagram * that are not {@link Node}s or {@link Link}s or {@link Adornment}s. * * This includes both data-bound and unbound parts, * and both top-level parts and parts inside {@link Group}s. * Use the {@link nodes} or {@link links} properties for getting the * collection of all {@link Node}s or {@link Link}s in the diagram. */ get parts(): Iterator; /** * Returns an iterator of all {@link Group}s that are at top-level, * in other words that are not themselves inside other Groups. * * This is useful for when you want to traverse the diagram's graph by recursing into Groups. */ findTopLevelGroups(): Iterator; /** * This read-only property returns the list of {@link Router}s that might run during this Diagram's update loop. * The typical usage when initializing the Diagram is to construct a particular Router and add it to this List. * * By default, this list contains one router, the undocumented AvoidsNodesRouter. * @since 3.0 */ get routers(): List; /** * Gets or sets the {@link Layout} used to position all of the top-level nodes and links in this Diagram. * By default this property is an instance of a simple {@link Layout} * that assigns positions to all parts that need it. * The value cannot be null and must not be shared with other Diagrams. */ get layout(): Layout; set layout(value: Layout); /** * Perform all invalid layouts. * If the optional argument is true, * this will perform all of the layouts ({@link Diagram.layout} and all {@link Group.layout}s), * not just the invalid ones. * * Under normal circumstances you should not need to call this method, * because layouts will be performed automatically after they become invalid. * However you may have disabled automatic layouts by setting {@link Layout.isInitial} * and/or {@link Layout.isOngoing} to false, or by restricting a Part's {@link Part.layoutConditions}. * If that is the case you might call this method * (perhaps due to a user command) to perform the layout at a time of your choosing. * @param invalidateAll - If true, this will explicitly set {@link Layout.isValidLayout} to false on each {@link Layout} in the diagram. */ layoutDiagram(invalidateAll?: boolean): void; /** * Gets or sets whether the Diagram tree structure is defined by * links going from the parent node to their children, or vice-versa. * By default this property is true: links go from the parent node to the child node. */ get isTreePathToChildren(): boolean; set isTreePathToChildren(value: boolean); /** * Returns an iterator of all top-level {@link Node}s that have no tree parents. * * This is useful for when you want to traverse the diagram's graph by starting at the root of each tree, * assuming that the diagram consists of one tree or a forest of trees. */ findTreeRoots(): Iterator; /** * (undocumented) * Gets or sets the conditions under which "child" nodes become not visible. * By default this property is {@link CollapsePolicy.TreeParent}: only the true tree parent node's * {@link Node.isTreeExpanded} property controls the visibility of a child node. * * You can set this to {@link CollapsePolicy.AllParents}, only if all of a node's * "parents" are collapsed will the node become hidden. * * You can set this to {@link CollapsePolicy.AnyParents}, if at least one of a node's * "parents" is collapsed, the node is hidden. * * Caution: cycles in the graph structure may cause all of the nodes in the cycle to become hidden. */ get treeCollapsePolicy(): CollapsePolicy; set treeCollapsePolicy(value: CollapsePolicy); /** * Register an event handler that is called when there is a {@link DiagramEvent} of a given name. * * See the {@link DiagramEvent} documentation for a complete listing of diagram event names and their purposes. * @param name - the name is normally capitalized, but this method uses case-insensitive comparison. * @param listener - a function that takes a {@link DiagramEvent} as its argument. * @returns this Diagram * @see {@link removeDiagramListener} */ addDiagramListener(name: DiagramEventName, listener: DiagramEventHandler): this; /** * Unregister a {@link DiagramEvent} handler. * * See the documentation for {@link DiagramEvent} for a complete listing of diagram event names and their purposes. * @param name - the name is normally capitalized, but this method uses case-insensitive comparison. * @param listener - a function that takes a {@link DiagramEvent} as its argument. * @see {@link addDiagramListener} */ removeDiagramListener(name: DiagramEventName, listener: DiagramEventHandler): void; /** * (undocumented) * Notify any {@link DiagramEvent} listeners by calling all event handlers registered by {@link addDiagramListener}. * @param name - the name is normally capitalized, but this method uses case-insensitive comparison. * @param obj - an optional subject of the event. * @param param - an optional parameter describing the change to the subject of the event. * @see {@link addDiagramListener} * @see {@link removeDiagramListener} */ raiseDiagramEvent(name: DiagramEventName, obj?: ObjectData, param?: any): void; /** * Undocumented. Used by Link.addOrthoPoints to get and initialize a PositionArray * representing the occupied areas of this Diagram. * @param clearunoccupied * @param group - limit avoidable nodes to members of this Group * @param skip - a Node (presumably an avoidable node) whose bounds are not declared "occupied" */ getPositions(clearunoccupied: boolean, group: Group | null, skip: Node | null): PositionArray; /** * (undocumented) */ get avoidanceCellSize(): Size; set avoidanceCellSize(value: Size); /** * (undocumented) */ get avoidanceLimit(): number; set avoidanceLimit(value: number); /** * Gets or sets number of milliseconds between autoscroll events. * The default value is 250. * @since 2.2 */ get autoScrollInterval(): number; set autoScrollInterval(value: number); /** * Gets or sets the Margin that describes the area along the inside edges of the viewport, * in viewport coordinates, where autoscrolling will occur while the mouse (pointer) is held there * during dragging or linking or drag-selecting. * * The default value is a Margin of 16 on all sides. * Increase this value in order to make it easier for the user to autoscroll by having * a larger area in which to hold the mouse (pointer) down during a dragging operation. * * When the mouse (pointer) drag point is within this region on the left or right sides, * the view will automatically scroll horizontally in that direction. * When the point is within the region on the top or bottom, the view will automatically scroll * vertically in that direction. * You can specify a Margin side of zero to disable autoscrolling in a particular direction; * a value of Margin(0,0,0,0) turns off autoscrolling in all four directions. */ get autoScrollRegion(): MarginLike; set autoScrollRegion(value: MarginLike); /** * (undocumented) * Called by DraggingTool and LinkingTool to implement auto-scrolling. * @param viewPt */ doAutoScroll(viewPt: Point): void; /** * (undocumented) * Stop any ongoing auto-scroll action. */ stopAutoScroll(): void; /** * (undocumented) * @virtual * @param viewPnt - in viewport coordinates * @returns in document coordinates */ computeAutoScrollPosition(viewPnt: Point): Point; /** * Create an SVGElement that contains a SVG rendering of the current Diagram. * * By default this method returns a snapshot of the visible diagram, but optional arguments give more options. *

* See the page on Making SVG for usage examples. * See the Minimal SVG Download sample, * which also demonstrates downloading an SVG file without involving a web server. * * Note that the resulting SVG DOM is not interactive -- it is a snapshot of this diagram at this time. * * At the current time methods such as {@link Diagram.makeImage}, * {@link Diagram.makeImageData} and {@link Diagram.makeSvg} do not work on {@link Overview}s. * * For the rendering to work, the diagram must have an HTML Div element as the {@link div}. * @param options - a JavaScript object detailing optional arguments for SVG creation, * described by {@link SvgRendererOptions} (and {@link DiagramRendererOptions} via inheritance) * @see {@link makeImage} */ makeSvg(options?: SvgRendererOptions): SVGElement | null; /** * (undocumented) * Add a renderer to the Diagram. This property is only used when building GoJS from source. * * When building from source, to include SVG rendering functionality for {@link Diagram.makeSvg}, * you must add the SVGSurface renderer with the name 'SVG': `myDiagram.addRenderer('SVG', new SVGSurface(myDiagram, document));` * * @param name - Name of the renderer * @param surface - Rendering class, either SVGSurface or CanvasSurface. */ addRenderer(name: string, surface: ISurface): void; /** * (undocumented) * Start or stop caching Group.findExternalLinksConnected */ cacheGroupExternalLinks(start: boolean): void; /** * Create an HTMLImageElement that contains a bitmap of the current Diagram. * This method is just a convenience function that creates an image, * sets its source to the returned string of {@link makeImageData}, * and returns a reference to that Image. * * See {@link makeImageData} for a complete explanation of possible options. * * By default this method returns a snapshot of the visible diagram, but optional arguments give more options. * * Note that a returned HTMLImageElement, either returned directly or passed to the callback function, * might not yet have the complete property set to true. * So if you need to draw the image immediately, you should check that property first. * If it is false, add a "load" listener to the HTMLImageElement that does the drawing you want. * * At the current time methods such as {@link Diagram.makeImage}, * {@link Diagram.makeImageData} and {@link Diagram.makeSvg} do not work on {@link Overview}s. * * For the rendering to work, the diagram must have an HTML Div element as the {@link div}. * @param options - a JavaScript object detailing optional arguments for image creation, to be passed to {@link makeImageData}. * @returns An HTML Image element, or null if a callback is specified, or null if there is no DOM. * @see {@link makeImageData} * @see {@link makeSvg} */ makeImage(options?: ImageRendererOptions): HTMLImageElement | null; /** * Create a bitmap of the current Diagram encoded as a base64 string, or returned as an ImageData object. * This method uses the toDataURL method of the HTMLCanvasElement to create the data URL, * or the getImageData method of the Canvas Context. * Unlike toDataURL, this method will not throw an error if cross-domain images * were drawn on the canvas, instead it will return a data URL of a bitmap with those images omitted. * * A simple example: * ```js * myDiagram.makeImageData({ * scale: 1.5, * size: new go.Size(100,100) * }); * ``` *

* See the page on Making Images for more usage examples. * * Note that a returned HTMLImageElement, either returned directly or passed to the callback function, * might not yet have the complete property set to true. * So if you need to draw the image immediately, you should check that property first. * If it is false, add a "load" listener to the HTMLImageElement that does the drawing you want. * * At the current time methods such as {@link Diagram.makeImage}, * {@link Diagram.makeImageData} and {@link Diagram.makeSvg} do not work on {@link Overview}s. * * For the rendering to work, the diagram must have an HTML Div element as the {@link div}. * @param options - a JavaScript object detailing optional arguments for image creation, * described by {@link ImageRendererOptions} (and {@link DiagramRendererOptions} via inheritance) * @returns An ImageData, or a base64-encoded string describing an image, or an HTMLImageElement, or null if a callback is specified. * @see {@link makeImage} */ makeImageData(options?: ImageRendererOptions): HTMLImageElement | ImageData | string | null; } /** * This is used in dragging methods to remember initial locations, for relative positioning and for cancellation. * You do not typically need to create these unless you are overriding tools. * * {@link CommandHandler.computeEffectiveCollection} returns a Map of Parts and DraggingInfo, * which is used as an argument for methods like {@link Diagram.computeMove}. * * {@link Diagram.moveParts} constructs a Map of Parts and DraggingInfo to record each Part's location offset during moves. * @since 2.0 */ export class DraggingInfo { /** * Optionally takes a Point that sets {@link point}. * @param pt */ constructor(pt?: Point); /** * Gets or sets the initial location for a dragged object. * This is most commonly the Part.location of the dragged object, or a rounded Part.location if snapping. */ get point(): Point; set point(value: Point); set shifted(value: Point); } /** * This class contains options for dragging and moving parts. * * This is used by {@link Diagram.moveParts}, {@link Diagram.computeMove}, and {@link DraggingTool.computeMove}. * * Both the {@link Diagram} and its {@link DraggingTool} have a DraggingOptions instance. * Typically, only the DraggingTool one is used, unless the Diagram has no DraggingTool defined. * * In typical {@link DraggingTool} operation you do not need to create or modify a DraggingOptions instance. * Setting properties on the DraggingTool such as {@link DraggingTool.isGridSnapEnabled} * sets the value on the {@link DraggingTool.dragOptions} instance for you. * @see {@link DraggingTool.dragOptions} * @since 2.0 */ export class DraggingOptions { /** * Whether or not the dragged parts snap to the {@link Diagram.grid}. * By default this property is false. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.isGridSnapEnabled}. */ isGridSnapEnabled: boolean; /** * If dragging with the {@link DraggingTool}, whether or not Parts snap to a grid (if applicable) in real-time, * or only at the end of the dragging transaction. * By default this property is true. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.isGridSnapRealtime}. */ isGridSnapRealtime: boolean; /** * Gets or sets the size of the grid cell used when snapping during a drag. * By default this property is the Size(NaN, NaN), which causes this tool to use the {@link Panel.gridCellSize} value of the {@link Diagram.grid}. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.gridSnapCellSize}. */ gridSnapCellSize: Size; /** * Gets or sets the {@link Spot} that specifies what point in the grid cell dragged parts snap to, * if the value of {@link isGridSnapEnabled} is true. By default this property is {@link Spot.TopLeft}. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.gridSnapCellSpot}. */ gridSnapCellSpot: Spot; /** * Gets or sets the snapping grid's origin point, in document coordinates, * if the value of {@link isGridSnapEnabled} is true. By default this property is the Point(NaN, NaN). * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.gridSnapOrigin}. */ gridSnapOrigin: Point; /** * Gets or sets whether the user can move a single {@link Link}, * disconnecting it from connected nodes and possibly connecting it to valid ports. * By default this property is false. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.dragsLink}. */ dragsLink: boolean; /** * Gets or sets whether moving or copying a node also includes all of the * node's tree children and their descendants, along with the links to those additional nodes. * By default this property is false. * * In typical {@link DraggingTool} operation this is set via {@link DraggingTool.dragsTree}. */ dragsTree: boolean; /** * Determines whether or not Groups will snap their member Parts in addition to themselves when moving. * By default this property is false. */ groupsSnapMembers: boolean; /** * Determines whether or not Groups will ensure their member Parts always move, * even if those member parts have {@link Part.copyable} and {@link Part.movable} set to false. * By default this property is true. */ groupsAlwaysMove: boolean; /** * Determines whether dragging a Group also drags its member Parts if there is no Group.placeholder. * By default this property is true. */ dragsMembers: boolean; constructor(init?: Partial); } /** * Used for the options arguments to {@link Diagram.makeImage}, {@link Diagram.makeImageData}, and {@link Diagram.makeSvg}. */ export interface DiagramRendererOptions { /** * The size of the created image, as a {@link Size}, limited by the {@link maxSize} property. * If no {@link scale} or {@link position} is specified then the diagram will be scaled to fit the given size. * If you set a size, you should also set a {@link position}. If you are scaling the diagram, you may also want to scale the size. */ size?: Size; /** * The scale of the diagram. If {@link scale} is specified and {@link size} is not, the resulting image will be sized to uniformly * fit the space needed for the given scale. * Can be constrained by the {@link maxSize} property. A scale value of `NaN` will * automatically scale to fit within the maxSize, but may be smaller, with a maximum computed scale of 1. */ scale?: number; /** * The maximum size of the created image, as a {@link Size}. * The default value is `(Infinity, Infinity)` for SVG and `(2000, 2000)` for images. * This is typically used when {@link scale} is specified and helps prevent accidental excessive memory usage, * which is especially needed in limited-memory environments. * You cannot use Infinity when providing a maximum size for an image -- consider calling {@link Diagram.makeSvg} instead. */ maxSize?: Size; /** * The position of the diagram, as a {@link Point}. * By default this is the position of {@link Diagram.documentBounds} with the {@link Diagram.padding} removed. * If a specific parts collection is used, by default this is the top-left diagram position of their collective bounds. * If you set a position, you should also set a {@link size}. */ position?: Point; /** * An iterator of {@link GraphObject}s, typically {@link Part}s, such as one from {@link Diagram.selection} or {@link Layer.parts}. * If GraphObjects are specified their containing Part will be drawn. By default all Parts are drawn except temporary parts (see {@link showTemporary}). */ parts?: Iterable | Array; /** * A {@link Margin} (or number) to pad the image with. If a size is specified, * the padding will not increase the image size, it will only offset the Diagram contents within the image. * The default value is a padding of `1`. */ padding?: MarginLike; /** * A valid CSS color to replace the default (transparent) canvas background. Any padding area is also colored. */ background?: BrushLike; /** * A boolean value, defaulting to false, * that determines whether or not temporary objects such as adornments are included in the image. */ showTemporary?: boolean; /** * A boolean value, defaulting to the value of **showTemporary**, * that determines whether or not the Grid Layer (containing {@link Diagram.grid}) is included in the image * regardless of the value of {@link showTemporary}. * This is useful if you want to include the grid but not adornments, or vice versa. */ showGrid?: boolean; /** * An HTML Document, defaulting to `window.document` (or the root object in other contexts) * This may be useful to set if you intend your Image or SVG to be opened in a new window. */ document?: Document; /** * The function to call when an image is finished creation. * It has one argument, which is of the type specified by the value of the {@link ImageRendererOptions.returnType} or SVG DOM. * If provided, call the callback when finished instead of returning immediately. This can be useful if you need to wait for image assets to load. * This also respects the {@link callbackTimeout}. * This argument is necessary if the {@link ImageRendererOptions.returnType} is `"blob"`, however a callback can be used with any {@link ImageRendererOptions.returnType}. * See the Minimal Image Blob Download sample for an example usage, * which also demonstrates downloading an image file without involving a web server. */ callback?: ((result: any) => void) | null; /** * If a {@link callback} is specified, the additional amount of time in milliseconds a call will wait before completeing. Right now, it will only wait if * image assets in the Diagram are not yet loaded. Default is 300 (milliseconds). */ callbackTimeout?: number; } /** * Used for the options argument to {@link Diagram.makeSvg}. */ export interface SvgRendererOptions extends DiagramRendererOptions { /** * A function with two arguments, GraphObject and SVGElement. * As the SVG elements are created representing each graph object, this function is called on them, * allowing you to modify the SVG as it is being built, to assign stylesheets, IDs, etc. Example: * ```js * elementFinished: (graphObject, SVGElement) => { * // set something on every SVG element that represents a GoJS TextBlock * if (graphObject instanceof go.TextBlock) SVGElement.setAttribute(...); * } * ``` */ elementFinished?: ((graphobj: GraphObject, svgelt: SVGElement) => void) | null; } /** * Used for the options argument to {@link Diagram.makeImage} and {@link Diagram.makeImageData}. */ export interface ImageRendererOptions extends DiagramRendererOptions { /** * The optional MIME type of the image. Valid values are typically `"image/png"` and `"image/jpeg"`. * Some browsers allow `"image/webp"`. The default value is `"image/png"`, and unrecognized values will defer to the default. */ type?: string; /** * The optional return type of the image data. Valid values are `"ImageData"`, `"Image"`, `"string"`, and `"blob"`. * The `"string"` option returns a base64 string representation of the image. * The `"ImageData"` option returns an `ImageData` object representation of the image. * The `"Image"` option returns an `HTMLImageElement` using `ImageData` as the `HTMLImageElement.src`. * The `"blob"` option requires that the {@link callback} property is also defined. * The default value is `"string"`, and unrecognized values will return a string. */ returnType?: string; /** * The optional details to pass to the HTMLCanvasElement's toDataURL function. * If the type is `"image/jpeg"` then this can be a number from `0` to `1`, inclusive, describing the desired jpeg quality. */ details?: number; } /** * Palette extends the Diagram class to allow objects to be dragged and placed onto other Diagrams. * Its {@link Diagram.layout} is a {@link GridLayout}. * The Palette is {@link Diagram.isReadOnly} but to support drag-and-drop its {@link Diagram.allowDragOut} is true. *

* For more discussion, see Introduction to Palettes. * See samples that make use of Palettes in the samples index. * * You can control the order of Parts in the palette in several manners: * - If you want to keep the order given by `myPalette.model.nodeDataArray`, * just set `myPalette.layout.sorting = go.GridSorting.Forwards` ({@link GridLayout.sorting}). * - If you want to sort based on some text string associated with each Part, just bind {@link Part.text}. * - If you want to sort more generally, set `myPalette.layout.comparer` ({@link GridLayout.comparer}). */ export class Palette extends Diagram { /** * @param div - A reference to a DIV HTML element or its ID as a string. * If no DIV is supplied, a Palette will be created in memory. The Palette's {@link Diagram.div} property * can then be set later on. * @param init - A JavaScript object specifying optional initialization properties object. * Can specify Palette properties, and Palette sub-properties, just as when initializing a Diagram. * Example: * ```js * { * allowZoom: false, * "animationManager.isEnabled": false * } * ``` */ constructor(div?: Element | string, init?: Partial); /** * @param init - A JavaScript object specifying optional initialization properties object. * Can specify Palette properties, and Palette sub-properties, just as when initializing a Diagram. * Example: * ```js * { * allowZoom: false, * "animationManager.isEnabled": false * } * ``` */ constructor(init?: Partial); } /** * An Overview is a {@link Diagram} that displays all of a different diagram, * with a rectangular box showing the viewport displayed by that other diagram. *

* For more discussion, see Introduction to Overviews. * See samples that make use of Overviews in the samples index. * * All you need to do is set {@link Overview.observed}. * For example: * * ```js * const myDiagram = new go.Diagram("myDiagramDIV"); * . . . other initialization . . . * * // create and initialize the Overview: * new go.Overview("myOverviewDIV").observed = myDiagram; * ``` * * The Overview draws what the observed Diagram is displaying, * so setting or modifying any diagram templates or template Maps has no effect. * * Animations are not shown in an Overview. * * At the current time methods such as {@link Diagram.makeImage}, * {@link Diagram.makeImageData} and {@link Diagram.makeSvg} do not work on Overviews. */ export class Overview extends Diagram { /** * @param div - A reference to a DIV HTML element or its ID as a string. * If no DIV is supplied, an Overview will be created in memory. The Overviews's {@link Diagram.div} property * can then be set later on. * @param init - Optional initialization properties. */ constructor(div?: Element | string, init?: Partial); /** * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Gets or sets the {@link Diagram} for which this Overview is * displaying a model and showing its viewport into that model. * * The value must be null or another Diagram, but may not be an Overview. */ get observed(): Diagram | null; set observed(value: Diagram | null); /** * Gets or sets the rectangular {@link Part} that represents the * viewport of the {@link observed} {@link Diagram}. * By default the part contains only a magenta {@link Shape}. * The box's {@link Part.selectionObject} is what is resized by the Overview to the apparent size of the observed diagram's viewport. */ get box(): Part; set box(value: Part); /** * Gets or sets whether this overview draws the temporary layers of the observed Diagram. * The default value is true. * Setting this property to false may improve drawing performance, * especially if the {@link Diagram.grid} is visible. * * Setting this property does not notify about any changed event. */ get drawsTemporaryLayers(): boolean; set drawsTemporaryLayers(value: boolean); /** * Gets or sets whether this overview draws the {@link Diagram.grid} of the observed Diagram, * if it is visible. The default value is true. * * This property is only considered when {@link drawsTemporaryLayers} is true. * Setting this to false may help improve drawing performance. * * Setting this property does not notify about any changed event. * @since 2.2 */ get drawsGrid(): boolean; set drawsGrid(value: boolean); /** * Gets or sets how long it waits before updating, in milliseconds. * The default value is zero. * Any new value must be a non-negative number. * * Setting this property does not notify about any changed event. * @since 2.2 */ get updateDelay(): number; set updateDelay(value: number); } /** * The {@link Diagram.commandHandler} implements various * commands such as {@link CommandHandler.deleteSelection} or {@link CommandHandler.redo}. * The CommandHandler includes keyboard event handling to interpret * key presses as commands. * * CommandHandlers cannot be shared amongst multiple Diagrams. * * You may define a CommandHandler subclass and override methods. * However you must seriously consider calling the base method in order to get its default behavior. * There may be situations where not calling the base method may cause subtle bugs, * but that depends on the method. * Please read the Introduction page on Extensions for how to override methods and how to call a base method. * * There is an example custom CommandHandler in the extensions directory: DrawCommandHandler.js, * which provides alignment commands and additional behaviors for the arrow keys. *

* For additional discussion, please read the Introduction page on Commands. *

Keyboard Shortcuts

* * The CommandHandler implements the following command bindings for keyboard input in {@link doKeyDown}: * - `Del` or `Backspace` invokes {@link deleteSelection} * - `Ctrl-X` or `Shift-Del` invokes {@link cutSelection} * - `Ctrl-C` or `Ctrl-Insert` invokes {@link copySelection} * - `Ctrl-V` or `Shift-Insert` invokes {@link pasteSelection} * - `Ctrl-A` invokes {@link selectAll} * - `Ctrl-Z` or `Alt-Backspace` invokes {@link undo} * - `Ctrl-Y` or `Ctrl-Shift-Z` or `Alt-Shift-Backspace` invokes {@link redo} * - `Up` or `Down` or `Left` or `Right` (arrow key) calls {@link Diagram.scroll} * - `PageUp` or `PageDown` calls {@link Diagram.scroll} * - `Home` or `End` calls {@link Diagram.scroll} * - `Space` invokes {@link scrollToPart} * - `Ctrl-- (minus) or Keypad--` invokes {@link decreaseZoom} * - `Ctrl-+ (plus) or Keypad-+` invokes {@link increaseZoom} * - `Ctrl-0` invokes {@link resetZoom} * - `Shift-Z` invokes {@link zoomToFit}; repeat to return to the original scale and position * - `Ctrl-G` invokes {@link groupSelection} * - `Ctrl-Shift-G` invokes {@link ungroupSelection} * - `F2` invokes {@link editTextBlock} * - `Menu Key` or Shift-F10 or Ctrl-Shift-\ invokes {@link showContextMenu} * - `Esc` invokes {@link stopCommand} * * On a Mac the Command key is used as the modifier instead of the Control key. * * On touch devices there is a default context menu that shows many commonly-used commands * when you hold a finger down on the diagram. */ export class CommandHandler { /** * The constructor produces a CommandHandler with the default key bindings. */ constructor(init?: Partial); /** * This read-only property returns the {@link Diagram} that is using this CommandHandler, * after {@link Diagram.commandHandler} has been set to this object. */ get diagram(): Diagram; /** * This method is called after this instance of CommandHandler has been associated with a Diagram * by being set as its {@link Diagram.commandHandler}. * * By default this method does nothing. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. */ doStart(): void; /** * This method is called just before this instance of CommandHandler will be de-associated with a Diagram * by being replaced as its {@link Diagram.commandHandler}. * * By default this method does nothing. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. */ doStop(): void; /** * This is called by tools to handle keyboard commands. * For most commands, this calls the "can..." predicate; if that returns true it calls the command method. * If GoJS handles a key-down event as a keyboard command, the underlying event will not bubble. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * There is an example custom CommandHandler in the extensions directory: DrawCommandHandler.js, * which implements additional behaviors for the arrow keys by overriding this method. * For additional discussion, please read the Introduction page on Commands. * * Starting in 3.0.7, this uses the value of {@link InputEvent.commandKey}. * @virtual */ doKeyDown(): void; /** * This is called by tools to handle keyboard commands. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ doKeyUp(): void; /** * This command cancels the operation of the current tool. * This is typically called when the user presses ESCAPE. * * If the current tool is a {@link ToolManager}, this clears the diagram's selection. * This then calls {@link Tool.doCancel} on the current tool. * @virtual * @see {@link canStopCommand} */ stopCommand(): void; /** * This predicate controls whether the user may stop the current tool. * This just returns true. * * This method may be overridden, but probably should not be overridden. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns true. * @see {@link stopCommand} */ canStopCommand(): boolean; /** * This command selects all of the selectable {@link Part}s in the diagram by setting {@link Part.isSelected} to true on each one. * This is normally invoked by the `Ctrl-A` keyboard shortcut. * * This method raises the "ChangingSelection" and "ChangedSelection" diagram events. * This ignores all parts in temporary layers. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canSelectAll} */ selectAll(): void; /** * This predicate controls whether or not the user can invoke the {@link selectAll} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true if {@link Diagram.allowSelect} is true. * @see {@link selectAll} */ canSelectAll(): boolean; /** * This command deletes the currently selected parts from the diagram. * This is normally invoked by the `Del` keyboard shortcut. * * This will first start a "Delete" transaction, then * raise the "SelectionDeleting" {@link DiagramEvent}, * call {@link Diagram.removeParts} on a perhaps extended collection of selected Parts, * raise the "SelectionDeleted" diagram event, * and finally commit the transaction. * * Because this command changes the selection, * this method also raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed within a transaction, but the selection events are raised outside the transaction. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canDeleteSelection} */ deleteSelection(): void; /** * This predicate controls whether or not the user can invoke the {@link deleteSelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowDelete} is true, and * if there are some selected {@link Part}s. * @see {@link deleteSelection} */ canDeleteSelection(): boolean; /** * This command copies the currently selected parts, {@link Diagram.selection}, from the {@link Diagram} into the clipboard. * This is normally invoked by the `Ctrl-C` keyboard shortcut. * * This makes a copy of the current selection by calling {@link copyToClipboard}. * This also raises the "ClipboardChanged" diagram event. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canCopySelection} */ copySelection(): void; /** * This predicate controls whether or not the user can invoke the {@link copySelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if {@link Diagram.allowCopy} is true, * if {@link Diagram.allowClipboard} is true, and * if there are some selected {@link Part}s. * @see {@link copySelection} */ canCopySelection(): boolean; /** * This command executes a {@link copySelection} followed by a {@link deleteSelection}. * This is normally invoked by the `Ctrl-X` keyboard shortcut. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canCutSelection} */ cutSelection(): void; /** * This predicate controls whether or not the user can invoke the {@link cutSelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowCopy} is true, * if {@link Diagram.allowDelete} is true, * if {@link Diagram.allowClipboard} is true, and * if there are some selected {@link Part}s. * @see {@link cutSelection} */ canCutSelection(): boolean; /** * Make a copy of the given collection of {@link Part}s * and stores it in a static variable acting as the clipboard. * * The clipboard is initially null. * It can hold a collection of copied {@link Part}s. * It also remembers the {@link Model.dataFormat} of the diagram * from which the parts were copied. * * This calls {@link Diagram.copyParts} in order to make a copy of the Parts for the clipboard. * The values of {@link copiesParentKey} and {@link copiesGroupKey} affect whether * a copied node data remembers its tree parent node (if in a {@link TreeModel}) or * its containing group (if in a {@link GraphLinksModel}). * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param coll - A collection of {@link Part}s. * If the value is null, the clipboard is cleared of all data. * @see {@link pasteFromClipboard} */ copyToClipboard(coll: Iterable | Array | null): void; /** * If the clipboard holds a collection of {@link Part}s, * and if the {@link Model.dataFormat} matches that stored in the clipboard, * this makes a copy of the clipboard's parts and adds the copies to this {@link Diagram}. * * This calls {@link Diagram.copyParts} in order to make a copy of the Parts in the clipboard and add them to this diagram. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns a collection of the newly pasted {@link Part}s, * or an empty Set if there was no data in the clipboard. * @see {@link copyToClipboard} */ pasteFromClipboard(): Set; /** * This command copies the contents of the clipboard into this diagram and makes those new parts the new selection. * This is normally invoked by the `Ctrl-V` keyboard shortcut. * * This calls {@link pasteFromClipboard} to add copies of {@link Part}s * into this diagram, and then selects all of the newly created parts. * This also raises the "ClipboardPasted" diagram event. * This method raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed in a transaction, but the selection events are raised outside the transaction. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pos - Point at which to center the newly pasted parts; if not present the parts are not moved. * @see {@link canPasteSelection} */ pasteSelection(pos?: Point | null): void; /** * This predicate controls whether or not the user can invoke the {@link pasteSelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param pos - Point at which to center the newly pasted parts; if not present the parts would not be moved. * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowInsert} is true, * if {@link Diagram.allowClipboard} is true, and * if the clipboard has parts in it. * @see {@link pasteSelection} */ canPasteSelection(pos?: Point): boolean; /** * This command calls {@link UndoManager.undo}. * This is normally invoked by the `Ctrl-Z` keyboard shortcut. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canUndo} */ undo(): void; /** * This predicate controls whether or not the user can invoke the {@link undo} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowUndo} is true, and * if the {@link UndoManager.canUndo} predicate returns true. * @see {@link undo} */ canUndo(): boolean; /** * This command calls {@link UndoManager.redo}. * This is normally invoked by the `Ctrl-Y` keyboard shortcut. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canRedo} */ redo(): void; /** * This predicate controls whether or not the user can invoke the {@link redo} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowUndo} is true, and * if the {@link UndoManager.canRedo} predicate returns true. * @see {@link redo} */ canRedo(): boolean; /** * This command decreases the {@link Diagram.scale} by a given factor. * This is normally invoked by the `Ctrl--` and `Keypad--` keyboard shortcuts. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param factor - This defaults to 1/{@link zoomFactor}. The value should be less than one and greater than zero. * @see {@link canDecreaseZoom} */ decreaseZoom(factor?: number): void; /** * This predicate controls whether or not the user can invoke the {@link decreaseZoom} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param factor - This defaults to 1/{@link zoomFactor}. The value should be less than one and greater than zero. * @returns This returns true if {@link Diagram.allowZoom} is true * and if the new scale is within the range of {@link Diagram.minScale} and {@link Diagram.maxScale}. * @see {@link decreaseZoom} */ canDecreaseZoom(factor?: number): boolean; /** * This command increases the {@link Diagram.scale} by a given factor. * This is normally invoked by the `Ctrl-+` and `Keypad-+` keyboard shortcuts. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param factor - This defaults to {@link zoomFactor}. The value should be greater than one. * @see {@link canIncreaseZoom} */ increaseZoom(factor?: number): void; /** * This predicate controls whether or not the user can invoke the {@link increaseZoom} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param factor - This defaults to {@link zoomFactor}. The value should be greater than one. * @returns This returns true if {@link Diagram.allowZoom} is true * and if the new scale is within the range of {@link Diagram.minScale} and {@link Diagram.maxScale}. * @see {@link increaseZoom} */ canIncreaseZoom(factor?: number): boolean; /** * This command sets the {@link Diagram.scale} to a new scale value, by default 1. * This is normally invoked by the `Ctrl-0` keyboard shortcut. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newscale - This defaults to {@link Diagram.defaultScale}, which is normally 1.0. The value should be greater than zero. * @see {@link canResetZoom} */ resetZoom(newscale?: number): void; /** * This predicate controls whether or not the user can invoke the {@link resetZoom} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param newscale - This defaults to {@link Diagram.defaultScale}, which is normally 1.0. The value should be greater than zero. * @returns This returns true if {@link Diagram.allowZoom} is true. * and if the new scale is within the range of {@link Diagram.minScale} and {@link Diagram.maxScale}. * @see {@link resetZoom} */ canResetZoom(newscale?: number): boolean; /** * This command changes the {@link Diagram.scale} so that the {@link Diagram.documentBounds} fits within the viewport. * If this command had been called before without any other zooming since then, * the original Diagram scale and position are restored. * This is normally invoked by the `Shift-Z` keyboard shortcut. * If you want the behavior where this command might restore the original diagram scale and position on a subsequent call, * set {@link isZoomToFitRestoreEnabled} to true. * * This animates zooming by default. {@link Diagram.zoomToFit} does not animate. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canZoomToFit} * @see {@link isZoomToFitRestoreEnabled} * @see {@link Diagram.zoomToFit} */ zoomToFit(): void; /** * This predicate controls whether or not the user can invoke the {@link zoomToFit} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true if {@link Diagram.allowZoom} is true. * @see {@link zoomToFit} */ canZoomToFit(): boolean; /** * This command scrolls the diagram to make a highlighted or selected Part visible in the viewport. * Call this command repeatedly to cycle through the {@link Diagram.highlighteds} collection, * if there are any Parts in that collection, or else in the {@link Diagram.selection} collection, * scrolling to each one in turn by calling {@link Diagram.centerRect}. * * This method animates to the scrolled part, and {@link Diagram.scrollToRect} does not. * * This is normally invoked by the `Space` keyboard shortcut. * If there is no argument and there is no highlighted or selected Part, this command does nothing. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * @virtual * @param part - This defaults to the first highlighted Part of {@link Diagram.highlighteds}, * or, if there are no highlighted Parts, the first selected Part. * @see {@link canScrollToPart} * @see {@link Diagram.scrollToRect} */ scrollToPart(part?: Part | null): void; /** * This predicate controls whether or not the user can invoke the {@link scrollToPart} command. * This returns false if there is no argument Part and there are no selected Parts. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param part - This defaults to the first selected Part of {@link Diagram.selection} * @returns This returns true if {@link Diagram.allowHorizontalScroll} and {@link Diagram.allowVerticalScroll} are true. * @see {@link scrollToPart} */ canScrollToPart(part?: Part | null): boolean; /** * This command collapses all expanded selected {@link Node}s. * This operation is performed within a "Collapse Tree" transaction. * Just before the end of the transaction this raises the "TreeCollapsed" {@link DiagramEvent}, * with a collection of collapsed {@link Node}s as the subject. * This currently has no default keyboard shortcut. * * This calls {@link Node.collapseTree} to perform the collapse, which will set {@link Node.isTreeExpanded} to false. * You may want to save the collapsed/expanded state to the model by using a TwoWay {@link Binding} on the "isTreeExpanded" property of your Nodes, * and perhaps also on the {@link Node.wasTreeExpanded} property. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param node - if supplied, ignore the selection and collapse this particular Node subtree. * @see {@link canCollapseTree} */ collapseTree(node?: Node | null): void; /** * This predicate controls whether the user can collapse expanded subtrees of {@link Node}s. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param node - if supplied, ignore the selection and consider collapsing this particular Node. * @see {@link collapseTree} */ canCollapseTree(node?: Node | null): boolean; /** * This command expands all collapsed selected {@link Node}s. * This operation is performed within an "Expand Tree" transaction. * Just before the end of the transaction this raises the "TreeExpanded" {@link DiagramEvent}, * with a collection of expanded {@link Node}s as the subject. * This currently has no default keyboard shortcut. * * This calls {@link Node.expandTree} to perform the expand, which will set {@link Node.isTreeExpanded} to true. * You may want to save the collapsed/expanded state to the model by using a TwoWay {@link Binding} on the "isTreeExpanded" property of your Nodes, * and perhaps also on the {@link Node.wasTreeExpanded} property. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param node - if supplied, ignore the selection and collapse this particular Node subtree. * @see {@link canExpandTree} */ expandTree(node?: Node | null): void; /** * This predicate controls whether the user can expand collapsed subtrees of {@link Node}s. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param node - if supplied, ignore the selection and consider expanding this particular Node. * @see {@link expandTree} */ canExpandTree(node?: Node | null): boolean; /** * This command adds a copy of {@link archetypeGroupData} to the diagram's model * to create a new {@link Group} and then adds the selected {@link Part}s to that new group. * This is normally invoked by the `Ctrl-G` keyboard shortcut. * * This creates a new {@link Group} by adding a copy of the {@link archetypeGroupData} to the model. * Each of the selected parts for which {@link Part.canGroup} is true * and for which {@link isValidMember} is true * is made a member of that new group. * If all of the selected groupable parts were members of a pre-existing group, * the new group also becomes a member of that pre-existing group, * if {@link isValidMember} is true for that existing group with the new group. * The new group becomes the only selected part. * This raises the "SelectionGrouped" diagram event. * This method also raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed in a "Group" transaction, but the selection events are raised outside the transaction. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @see {@link canGroupSelection} */ groupSelection(): void; /** * This predicate controls whether or not the user can invoke the {@link groupSelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns This returns true: * if the {@link archetypeGroupData} is not null, * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowInsert} is true, * if {@link Diagram.allowGroup} is true, * if {@link Diagram.model} is a {@link GraphLinksModel}, and * if there is any selected {@link Part} that can be {@link Part.canGroup}ed. * @see {@link groupSelection} */ canGroupSelection(): boolean; /** * This predicate is called to determine whether a Node may be added as a member of a Group. * This always checks to make sure no group might become a member of itself, either directly or indirectly. * If the Group has a {@link Group.memberValidation} predicate and if it returns false, this method returns false. * If this CommandHandler has a {@link memberValidation} predicate and if it returns false, this method returns false. * Otherwise this will return true. *

* For a more general discussion of validation, see Introduction to Validation. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - this may be null if the node is being added as a top-level node. * @param part - a Part, usually a Node, possibly another Group, but not a Link or an Adornment. * @returns true if OK to add the node to the group. */ isValidMember(group: Group | null, part: Part): boolean; /** * This command removes selected groups from the diagram without removing their members from the diagram. * This is normally invoked by the `Ctrl-Shift-G` keyboard shortcut. * * For the given group, or if not supplied, each selected {@link Group} that is {@link Group.ungroupable}, * expand the subgraph and change all of its member parts to be members of the group that the selected group node is in. * (If the selected group is a top-level node, i.e. not a member of any group node, its members become top-level parts too.) * All of those selected groups are deleted. * All of the reparented member parts are selected. * * This raises the "SelectionUngrouped" diagram event. * This method also raises the "ChangingSelection" and "ChangedSelection" diagram events. * Changes are performed in an "Ungroup" transaction, but the selection events are raised outside the transaction. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and consider ungrouping this particular Group. * @see {@link canUngroupSelection} */ ungroupSelection(group?: Group | null): void; /** * This predicate controls whether or not the user can invoke the {@link ungroupSelection} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and consider ungrouping this particular Group. * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowDelete} is true, * if {@link Diagram.allowUngroup} is true, * if {@link Diagram.model} is a {@link GraphLinksModel}, and * if there are any selected {@link Group}s that are {@link Group.ungroupable}. * @see {@link ungroupSelection} */ canUngroupSelection(group?: Group | null): boolean; /** * Make sure all of the unnested {@link Part}s in the given collection * are removed from any containing {@link Group}s. * * This sets {@link Part.containingGroup} to null on each Part that is * not a member of another Part in the argument collection. * If the check argument to this method is supplied and true, * this will call {@link isValidMember} on each part, passing null as the first argument. * * This functionality is similar to {@link ungroupSelection}, * except that this is not a command (there is no transaction and this does not raise a {@link DiagramEvent}) * and the parts are necessarily becoming top-level parts * (whereas ungrouping would add them to the Group containing the Group being ungrouped). * * This function is typically called in a {@link Diagram.mouseDrop} event handler * in order to remove the selected Parts from whatever {@link Group} they had been in. * * If you want to add Parts to be members of a Group, call {@link Group.addMembers}. * If you want to remove Parts completely from a Diagram, call {@link Diagram.removeParts}. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param coll - a collection of Parts. * @param check - whether to call {@link isValidMember} to confirm that changing the Part to be a top-level Part is valid. * @returns true if all non-Links were changed to be top-level Parts in this Diagram; false if some Parts or Nodes were not able to be added. */ addTopLevelParts(coll: Iterable | Array, check?: boolean): boolean; /** * This command collapses all expanded selected {@link Group}s. * This operation is performed within a "Collapse SubGraph" transaction. * Just before the end of the transaction this raises the "SubGraphCollapsed" {@link DiagramEvent}, * with a collection of collapsed {@link Group}s as the subject. * This currently has no default keyboard shortcut. * * This calls {@link Group.collapseSubGraph} to perform the collapse, which will set {@link Group.isSubGraphExpanded} to false. * You may want to save the collapsed/expanded state to the model by using a TwoWay {@link Binding} on the "isSubGraphExpanded" property of your Groups, * and perhaps also on the {@link Group.wasSubGraphExpanded} property. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and collapse this particular Group. * @see {@link canCollapseSubGraph} */ collapseSubGraph(group?: Group | null): void; /** * This predicate controls whether the user can collapse expanded {@link Group}s. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and consider collapsing this particular Group. * @see {@link collapseSubGraph} */ canCollapseSubGraph(group?: Group | null): boolean; /** * This command expands all collapsed selected {@link Group}s. * This operation is performed within an "Expand SubGraph" transaction. * Just before the end of the transaction this raises the "SubGraphExpanded" {@link DiagramEvent}, * with a collection of expanded {@link Group}s as the subject. * This currently has no default keyboard shortcut. * * This calls {@link Group.expandSubGraph} to perform the collapse, which will set {@link Group.isSubGraphExpanded} to true. * You may want to save the collapsed/expanded state to the model by using a TwoWay {@link Binding} on the "isSubGraphExpanded" property of your Groups, * and perhaps also on the {@link Group.wasSubGraphExpanded} property. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and expand this particular Group. * @see {@link canExpandSubGraph} */ expandSubGraph(group?: Group | null): void; /** * This predicate controls whether the user can expand collapsed {@link Group}s. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param group - if supplied, ignore the selection and consider expanding this particular Group. * @see {@link expandSubGraph} */ canExpandSubGraph(group?: Group | null): boolean; /** * This command starts in-place editing of a {@link TextBlock} in the selected {@link Part}. * This is normally invoked by the `F2` keyboard shortcut. * * This starts the {@link TextEditingTool} to have the user enter or modify the text string and finally set the {@link TextBlock.text}. * You may want to save the new string to the model by using a TwoWay {@link Binding} on the "text" property of your TextBlock. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param textblock - the {@link TextBlock} to start editing. * @see {@link canEditTextBlock} */ editTextBlock(textblock?: TextBlock | null): void; /** * This predicate controls whether or not the user can invoke the {@link editTextBlock} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param textblock - the {@link TextBlock} to consider editing. * @returns This returns true: * if the diagram is not {@link Diagram.isReadOnly}, * if {@link Diagram.allowTextEdit} is true, * if there is a {@link ToolManager.textEditingTool}, and * if there is any selected {@link Part} for which {@link Part.canEdit} is true. * @see {@link editTextBlock} */ canEditTextBlock(textblock?: TextBlock | null): boolean; /** * This command opens the context menu for a selected Part or given GraphObject, or else for the whole Diagram. * This is normally invoked by the `Menu` keyboard shortcut. * * The given GraphObject must have a {@link GraphObject.contextMenu} * defined in order to show anything. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param obj - a GraphObject or Diagram with a contextMenu defined. * If none is given, this method will use the first selected object, or else the Diagram. * The method will simulate a right-button click at the middle of the GraphObject or, * if a Diagram, at the current mouse position if it is in the viewport. * @see {@link canShowContextMenu} */ showContextMenu(obj?: GraphObject | Diagram | null): void; /** * This predicate controls whether or not the user can invoke the {@link showContextMenu} command. * * This method may be overridden, but you should consider calling this base method in order to get all of its functionality. * This method must not have any side-effects. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param obj - a GraphObject or Diagram with a contextMenu defined. * If none is given, this method will use the first selected object, or else the Diagram. * @see {@link showContextMenu} */ canShowContextMenu(obj?: GraphObject | Diagram | null): boolean; set copiesClipboardData(value: boolean); /** * Gets or sets whether {@link copySelection} should also copy Links that connect with selected Nodes. * The default value is true. * Setting this property does not raise any events. * * The {@link DraggingTool.copiesEffectiveCollection} property serves a similar role for the {@link DraggingTool} * when the user holds down the control key to modify the drag into a copy operation. */ get copiesConnectedLinks(): boolean; set copiesConnectedLinks(value: boolean); /** * Gets or sets whether {@link deleteSelection} should also delete links that are connected to nodes that are deleted. * The default value is true. * Setting this property does not raise any events. */ get deletesConnectedLinks(): boolean; set deletesConnectedLinks(value: boolean); /** * Gets or sets whether {@link copySelection} should also copy subtrees. * The default value is false. * Setting this property does not raise any events. * * The {@link DraggingTool.dragsTree} property serves a similar role for the {@link DraggingTool} * for both moving and copying operations. */ get copiesTree(): boolean; set copiesTree(value: boolean); /** * Gets or sets whether {@link deleteSelection} should also delete subtrees. * The default value is false. * Setting this property does not raise any events. */ get deletesTree(): boolean; set deletesTree(value: boolean); /** * Gets or sets whether {@link copySelection} and {@link copyToClipboard} copy the node data property * whose value is the tree-parent node data's key. * * Set this property to true if you want a copy/paste of a node to automatically have the new node be a tree-child of the original tree-parent node. * Caution: this only has an effect if the Diagram's {@link Diagram.model} is a {@link TreeModel}. * * The default value is false. */ get copiesParentKey(): boolean; set copiesParentKey(value: boolean); /** * Gets or sets whether {@link copySelection} and {@link copyToClipboard} copy the node data property * whose value is the containing group data's key. * * Set this property to true if you want a copy/paste of a node to automatically have the new node be a member of the original group. * Caution: this only has an effect if the Diagram's {@link Diagram.model} is a {@link GraphLinksModel}. * * The default value is false. */ get copiesGroupKey(): boolean; set copiesGroupKey(value: boolean); /** * Gets or sets a data object that is copied by {@link groupSelection} * when creating a new Group. * * The default value is null. * If you set this to an Object, be sure that {@link GraphLinksModel.isGroupForNodeData} is true for that object. * Setting this property does not raise any events. */ get archetypeGroupData(): ObjectData | null; set archetypeGroupData(value: ObjectData | null); /** * Gets or sets the predicate that determines whether or not a node may become a member of a group. * This predicate is called in addition to any existing group's {@link Group.memberValidation} predicate. * The default predicate is null, which is equivalent to simply returning true. * The predicate may be called passing null as the first argument (the Group) -- * this asks whether it is OK to make the second argument (the Part, but not a Link) a top-level Part of the diagram. *

* For a more general discussion of validation, see Introduction to Validation. * * The function, if supplied, must not have any side-effects. */ get memberValidation(): ((aGroup: Group | null, somePart: Part) => boolean) | null; set memberValidation(value: ((aGroup: Group | null, somePart: Part) => boolean) | null); /** * (undocumented) * Deprecated in favor of {@link Diagram.defaultScale}. */ get defaultScale(): number; set defaultScale(value: number); /** * Gets or sets the amount by which {@link decreaseZoom} and {@link increaseZoom} change * the {@link Diagram.scale}. * * The default value is 1.05 (5%). * The value must be a number larger than 1.0. * Setting this property does not raise any events. */ get zoomFactor(): number; set zoomFactor(value: number); /** * Gets or sets whether the {@link zoomToFit} command ever restores the previous * Diagram scale and position. * When this property is false, this command always calls {@link Diagram.zoomToFit}. * * The default value is false. * Setting this property does not raise any events. * @since 2.2 */ get isZoomToFitRestoreEnabled(): boolean; set isZoomToFitRestoreEnabled(value: boolean); set scrollToPartPause(value: number); /** * Find the actual collection of nodes and links to be moved or copied, * given an initial collection. * This includes links that connected at both ends to nodes being moved or copied, * members of {@link Group}s, and if {@link DraggingTool.dragsTree} is true, * this includes nodes and links that are "tree" descendants from selected nodes. * * Note that this does not return a simple collection of {@link Part}s, * but a {@link Map | go.Map} associating a chosen {@link Part} * with an Object holding its original location Points as the value of the "point" property. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param parts - A {@link Set | go.Set} or {@link List} of {@link Part}s. * @param options - Potential options for the collection computation. If not specified, this uses the DraggingTool's drag options. * @returns a Map mapping {@link Part}s to DraggingInfo Objects * that have a "point" property remembering the original location of that Part. * @since 2.0 */ computeEffectiveCollection(parts: Iterable, options?: DraggingOptions): Map; } /** * This enumeration specifies possible values for {@link GraphObject.stretch}. * @since 3.0 */ export declare enum Stretch { /** * Do not scale the object; there may be clipping in one or both directions if the available dimensions are too small. */ None = 0, /** * Scale the object depending on context, for instance uniformly for a "Circle" figure and non-uniformly for an "Ellipse" figure. */ Default = 1, /** * Scale the object as much as possible in the y-axis. */ Vertical = 4, /** * Scale the object as much as possible in the x-axis. */ Horizontal = 5, /** * Scale the object in both directions so as to fit exactly in the given bounds; * there is no clipping, but the aspect ratio may change, causing the object to appear stretched. */ Fill = 2 } /** * This enumeration specifies possible values for {@link GraphObject.segmentOrientation}. * @since 3.0 */ export declare enum Orientation { /** * Do not rotate the object along the segment. */ None = 0, /** * Rotate the object to have the same angle as the segment it is at; use this orientation for arrow heads. */ Along = 21, /** * Rotate the object clockwise 90 degrees to be perpendicular to the angle of the segment it is at. */ Plus90 = 22, /** * Rotate the object counter-clockwise 90 degrees to be perpendicular to the angle of the segment it is at. */ Minus90 = 23, /** * Rotate the object to be 180 degrees opposite from the angle of the segment it is at. */ Opposite = 24, /** * Rotate the object to have the same angle as the segment it is at, just like {@link Along}, but never upside down; * this is typically only used for {@link TextBlock}s or {@link Panel}s that contain text. */ Upright = 25, /** * Rotate the object clockwise 90 degrees to be perpendicular to the angle of the segment it is at, just like {@link Plus90}, but never upside down; * this is typically only used for {@link TextBlock}s or {@link Panel}s that contain text. */ Plus90Upright = 26, /** * Rotate the object counter-clockwise 90 degrees to be perpendicular to the angle of the segment it is at, just like {@link Minus90}, but never upside down; * this is typically only used for {@link TextBlock}s or {@link Panel}s that contain text. */ Minus90Upright = 27, /** * Rotate the object to have the same angle as the segment it is at, but never upside down and never angled more than +/- 45 degrees: * when the segment's angle is with 45 degrees of vertical (90 or 270 degrees), the object's angle is set to zero; * this is typically only used for {@link TextBlock}s or {@link Panel}s that contain text. */ Upright45 = 28 } /** * This enumeration specifies possible values for {@link Picture.flip} and {@link TextBlock.flip}. * @since 3.0 */ export declare enum Flip { /** * Draw the object normally. */ None = 0, /** * Draw the object upside-down, with Y coordinate points increasing upwards. */ Vertical = 1, /** * Draw the object mirror-image, with X coordinate points increasing towards the left. */ Horizontal = 2, /** * Draw the object with both X and Y coordinates reversed. */ Both = 3 } /** * A type that describes a constructor. Used in the declaration of GraphObject.make. */ export type ConstructorType) => InstanceType> = new (...args: Array) => InstanceType; /** * A type that declares which types may be passed as arguments, depending on the type of instance being built. * Used in the declaration of GraphObject.make. */ export type MakeAllow, C, E> = (InstanceType extends C ? E : never); /** * This is the abstract base class for all graphical objects. * Classes inheriting from GraphObject include: * {@link Shape}, {@link TextBlock}, {@link Picture}, and {@link Panel}. * From the Panel class the {@link Part} class is derived, from which the * {@link Node} and {@link Link} classes derive. * * It is very common to make use of the static function {@link GraphObject.make} in order to build up * a visual tree of GraphObjects. You can see many examples of this throughout the * Introduction, starting at Building Objects, * and the Samples, starting with Minimal Sample. * * Since GraphObject is an abstract class, programmers do not create GraphObjects themselves, * but this class defines many properties used by all kinds of GraphObjects. * * The only visual property on GraphObject is {@link background}. * However one can control whether the GraphObject is drawn at all by setting {@link visible}, * or by setting {@link opacity} to zero if you still want the GraphObject to occupy space. * Call the {@link isVisibleObject} predicate to determine whether the object is visible and * all of its containing panels are visible. * Also, if you want to control whether any mouse or touch events "see" the GraphObject, * you can set {@link pickable} to false. * * For more information about specifying how things get drawn, see the properties on the * {@link Shape}, {@link TextBlock}, and {@link Picture} classes. *

GraphObject Sizing

* * GraphObject defines most of the properties that cause objects to size themselves differently. * The most prominent ones include: * - The {@link desiredSize}, {@link minSize}, and {@link maxSize} properties are used to * explicitly set or limit the size of visual elements. {@link width} and {@link height} are * convenience properties that set the {@link desiredSize} width and height, respectively. * - The {@link angle} and {@link scale} properties are used to transform visual elements. * - The {@link stretch} property determines how a GraphObject will fill its visual space, * contextually granted to it by its containing {@link Panel}. Top-level ({@link Part}) * GraphObjects are not affected by this property because they are always granted infinite space. * * All GraphObjects in a Diagram are measured and then arranged by their containing {@link Panel}s in a tree-like fashion. * After measuring and arranging, a GraphObject will have valid values for the read-only * properties {@link naturalBounds}, {@link measuredBounds}, and {@link actualBounds}. * * - The {@link naturalBounds} of a GraphObject describe its local size, * without any transformations ({@link scale}, {@link angle}) affecting it. * - The {@link measuredBounds} of a GraphObject describe its size within its containing Panel. * - The {@link actualBounds} of a GraphObject describe its position and given size inside of its panel. * This size may be smaller than {@link measuredBounds}, for instance if a GraphObject with a large {@link desiredSize} * is placed in a {@link Panel} of a smaller {@link desiredSize}. Smaller {@link actualBounds} than {@link measuredBounds} * typically means an object will be cropped. * *

* See the Introduction page on sizing * for usage information and examples. *

GraphObject Size and Position within Panel

* Several GraphObject properties guide the containing {@link Panel} for how to size and position the object within the panel. * * - The {@link alignment} specifies where the object should be relative to some area of the panel. * For example, an alignment value of {@link Spot.BottomRight} means that the GraphObject should be at the bottom-right corner of the panel. * - The {@link alignmentFocus} specifies precisely which point of the GraphObject should be aligned at the {@link alignment} spot. * - The {@link column} and {@link row} properties are only used by {@link Panel.Table} panels, to indicate where the GraphObject should be. * - The {@link columnSpan} and {@link rowSpan} properties tell the {@link Panel.Table} panel how large the GraphObject should be. * - The {@link isPanelMain} property indicates to some kinds of {@link Panel}s that the GraphObject is the "primary" object * that other panel children should be measured with or positioned in. * - The {@link margin} property tells the containing {@link Panel} how much extra space to put around this GraphObject. * - The {@link position} property is used to determine the relative position of GraphObjects when they are elements of a {@link Panel.Position} panel. * *

* See the Introduction page on Panels * and Table Panels for an overview of the capabilities. *

Top-level GraphObjects are Parts

* * A {@link Part} is a derived class of GraphObject representing a top-level object. * All top-level GraphObjects must be Parts, and Node, Link, Group, and Adornment derive from Part. * The position of a Part determines the point of the Part's top-left corner in document coordinates. * See also {@link Part.location}, which supports an way to specify the position based on a different * spot of a different element within the Part. * * There are several read-only properties that help navigate up the visual tree. * - {@link panel} returns the {@link Panel} that directly contains this GraphObject * - {@link part} returns the {@link Part} that this GraphObject is in, perhaps via intervening Panels; * this is frequently used in order to get to the model data, {@link Panel.data} * - {@link layer} returns the {@link Layer} that this GraphObject's Part is in * - {@link diagram} returns the {@link Diagram} that this GraphObject's Part's Layer is in * *

* See the Visual Tree sample * for a diagram displaying the visual tree of a simple diagram. *

User Interaction

* * GraphObjects have several properties enabling dynamic customizable interaction. * There are several definable functions that execute on input events: {@link mouseDragEnter}, * {@link mouseDragLeave}, {@link mouseDrop}, {@link mouseEnter}, {@link mouseHold}, * {@link mouseHover}, {@link mouseLeave}, and {@link mouseOver}. * For example, you could define mouse enter-and-leave event handlers to modify the appearance of a link * as the mouse passes over it: * ```js * myDiagram.linkTemplate = * new go.Link().add( * new go.Shape( * { * strokeWidth: 2, stroke: "gray", // default color is "gray" * // here E is the InputEvent and OBJ is this Shape * mouseEnter: (e, obj) => { obj.strokeWidth = 4; obj.stroke = "dodgerblue"; }, * mouseLeave: (e, obj) => { obj.strokeWidth = 2; obj.stroke = "gray"; } * }) * ); * ``` * * There are {@link click}, {@link doubleClick}, and {@link contextClick} functions * that execute when a user appropriately clicks the GraphObject. * These click functions are called with the {@link InputEvent} as the first argument * and this GraphObject as the second argument. * For example, you could define a click event handler on a Node that goes to another page: * ```js * myDiagram.nodeTemplate = * new go.Node("Auto", * { // second arg will be this GraphObject, which in this case is the Node itself: * click: (e, node) => { * window.open("https://en.wikipedia.org/Wiki/" + node.data.key); * } * }).add( * new go.Shape("RoundedRectangle") * .bind("fill", "color"), * new go.TextBlock({ name: "TB", margin: 3 }) * .bind("text", "key"), * ); * ``` * * Note: you may prefer defining {@link DiagramEvent} listeners on the {@link Diagram} * rather than on individual GraphObjects. DiagramEvents also include more general events that * do not necessarily correspond to input events. * * The properties {@link actionCancel}, {@link actionDown}, {@link actionMove}, * and {@link actionUp} define functions to execute when the GraphObject's {@link isActionable} property * is set to true (default false). See the {@link ActionTool} for more detail. *

* See the Introduction page on Events for a more general discussion. *

GraphObjects as Ports

* * In GoJS, {@link Link}s can only connect to elements within a {@link Node} * that are specified as "ports", and by default the only port is the Node itself. * Setting the {@link portId} of a GraphObject inside a Node allows that object to act as a port. * Note: the only kind of model that can save which port a link is connected with, i.e. portIds that are not an empty string, * is a {@link GraphLinksModel} whose {@link GraphLinksModel.linkFromPortIdProperty} and * {@link GraphLinksModel.linkToPortIdProperty} have been set to name properties on the link data objects. * * GraphObjects have several properties that are only relevant when they are acting as ports. * These port-related properties are: * - {@link portId}, which must be set to a string that is unique within the {@link Node}, * in order for this GraphObject to be treated as a "port", rather than the whole node * - {@link fromSpot} and {@link toSpot}, where a link should connect with this port * - {@link fromEndSegmentLength} and {@link toEndSegmentLength}, the length of the link segment adjacent to this port * - {@link fromShortLength} and {@link toShortLength}, the distance the link should terminate before touching this port * - {@link fromLinkable} and {@link toLinkable}, whether the user may draw links connecting with this port * - {@link fromLinkableDuplicates} and {@link toLinkableDuplicates}, whether the user may draw multiple links between the same pair of ports * - {@link fromLinkableSelfNode} and {@link toLinkableSelfNode}, whether the user may draw a link between ports on the same node * - {@link fromMaxLinks} and {@link toMaxLinks}, to limit the number of links connecting with this port in a particular direction * *

* See the Introduction page on ports * and link routing * and link connection points * for port usage information and examples. *

GraphObjects as labels on a Link

* * GraphObjects can also be used as "labels" on a {@link Link}. * In addition to the {@link alignmentFocus} property, these properties direct a Link Panel * to position a "label" at a particular point along the route of the link, in a particular manner: * - {@link segmentIndex}, which segment the label should be on * - {@link segmentFraction}, how far along the segment the label should be * - {@link segmentOffset}, where the label should be positioned relative to the segment * - {@link segmentOrientation}, how the label should be rotated relative to the angle of the segment * *

* See the Introduction page on link labels * for examples of how to make use of labels on Links. *

Interactive Behavior

* * There are several properties that specify fairly high-level interactive behavior: * - {@link cursor}, a CSS string specifying a cursor * - {@link contextMenu}, an {@link Adornment} * - {@link toolTip}, an {@link Adornment} * *

* For more information, please read the Introduction page about Context Menus * and the page about ToolTips. *

* Also see the Basic sample * for examples of how to show context menus and tooltips. */ export abstract class GraphObject { /** * This is an abstract class, so you should not use this constructor. */ constructor(); /** * Copies properties from this object to the given object, which must be of the same class. * This is called by {@link copy}. * This method may be overridden. * * For every property that you add to a subclass of a GraphObject-inheriting class, * in this method you should assign its value to the copied object. * For performance reasons you should set all of the same properties to this * that the constructor does, and in the same order. * * For example, let us define a custom {@link Link} class and add two properties: * * ```js * class CustomLink extends go.Link { * constructor() { * super(); * tnis._someNewProperty = 17; * tnis._someNewProperty2 = []; // an Array * } * * cloneProtected(copy) { * // Always call the base method in an override * super.cloneProtected(copy); * // assign every new property to the copy: * copy._someNewProperty = this._someNewProperty; * copy._someNewProperty2 = this._someNewProperty2.slice(0); // make a copy of the Array * } * } * ``` * * This ensures that copies of GraphObjects and their subclasses are faithful reproductions. * Consider for properties that are references to objects whether the reference should be shared * or whether that object value should be copied as well, resulting in a less shallow copy. * This is demonstrated above by making a copy of the property value that is an Array, * so that modifications to the Array will not be shared by copies of the CustomLink. * Further copies of the Array items might be warranted, depending on their purpose. * * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param copy */ protected cloneProtected(copy: this): void; /** * Creates a deep copy of this GraphObject and returns it. * This method is the same as a clone for simple GraphObjects * such as {@link Shape}, {@link TextBlock}, and {@link Picture}. * For {@link Panel} this method copies the visual tree of GraphObjects that it contains. * @virtual */ copy(): this; /** * @deprecated See {@link Stretch.None}, {@link Flip.None}, {@link GeometryStretch.None}, {@link ImageStretch.None}, {@link ReshapingBehavior.None}. */ static readonly None = 0; /** * @deprecated See {@link Stretch.Default}, {@link GeometryStretch.Default}. */ static readonly Default = 1; /** * @deprecated See {@link Stretch.Fill}, {@link GeometryStretch.Fill}. */ static readonly Fill = 2; /** * @deprecated See {@link Stretch.Vertical}. */ static Vertical: any; /** * @deprecated See {@link Stretch.Horizontal}. */ static Horizontal: any; /** * @deprecated See {@link GeometryStretch.Uniform}, {@link ImageStretch.Uniform}, {@link ViewboxStretch.Uniform}. */ static readonly Uniform = 6; /** * @deprecated See {@link ImageStretch.UniformToFill}, {@link ViewboxStretch.UniformToFill}. */ static readonly UniformToFill = 7; /** * @deprecated See {@link Flip.Vertical}. */ static readonly FlipVertical = Flip.Vertical; /** * @deprecated See {@link Flip.Horizontal}. */ static readonly FlipHorizontal = Flip.Horizontal; /** * @deprecated See {@link Flip.Both}. */ static readonly FlipBoth = Flip.Both; /** * Call this method to notify that some state has changed. * * @param change - specifies the general nature of the change; * permissible values include {@link ChangeType} values. * @param propertyname - names the property that was modified. * @param obj - the object that was modified. * @param oldval - the previous or older value. * @param newval - the next or newer value. * @param oldparam - an optional value that helps describe the older value. * @param newparam - an optional value that helps describe the newer value. */ raiseChangedEvent(change: ChangeType, propertyname: string, obj: ObjectData, oldval: any, newval: any, oldparam?: any, newparam?: any): void; /** * Returns the Point in document coordinates for a given Spot in this object's bounds * or for a Point in local coordinates. * * For example, for an instance of a Node like this: * ```js * myDiagram.nodeTemplate = * new go.Node("Auto").add( * new go.Shape("RoundedRectangle") * .bind("fill", "color"), * new go.TextBlock({ name: "TB", margin: 3 }) * .bind("text", "key") * ); * ``` * where the Node is positioned at `100, 200`, * ```js * node.findObject("TB").getDocumentPoint(go.Spot.Center) * ``` * could return a Point that is approximately at `122, 213`. * @param local - a real Spot describing a relative location in or near this GraphObject, or a real Point in local coordinates. * @param result - an optional Point that is modified and returned. * @returns in document coordinates. * @see {@link getDocumentBounds} * @see {@link getLocalPoint} */ getDocumentPoint(local: Spot | Point, result?: Point): Point; /** * Returns the Rect in document coordinates for this object's bounds. * If this GraphObject is a Part, the rect will be identical to its {@link actualBounds}. * @param result - an optional Rect that is modified and returned. * @returns in document coordinates. * @see {@link getDocumentPoint} * @since 2.0 */ getDocumentBounds(result?: Rect): Rect; /** * Returns the effective angle that the object is drawn at, in document coordinates, normalized to between 0 and 360. * * Basically this adds together all of the rotation declared by this {@link angle} and the angles of all of its containing Panels, including the Part. */ getDocumentAngle(): number; /** * Returns the total scale that the object is drawn at, in document coordinates. * * Basically this multiplies together this {@link scale} with the scales of all of its containing Panels, including the Part. */ getDocumentScale(): number; /** * Given a Point in document coordinates, returns a new Point in local coordinates. * * For example, if you have a mouse event whose {@link InputEvent.documentPoint} is at `122, 213`, * and if you have a Node whose {@link position} is at `100, 200`, * `node.getLocalPoint(e.documentPoint)` could return a Point that is at `22, 13`. * For a GraphObject within the Node named "TB", * ```js * node.findObject("TB").getLocalPoint(e.documentPoint) * ``` * could return a Point that is at `15.7, 6.7`, * if that "TB" object is positioned somewhat inside the bounds of the Node. * @param p - a real Point in document coordinates. * @param result - an optional Point that is modified and returned. * @returns The corresponding Point in local coordinates. * @see {@link getDocumentPoint} */ getLocalPoint(p: Point, result?: Point): Point; /** * Gets or sets whether or not this GraphObject will be shadowed inside a Part that has {@link Part.isShadowed} set to true. * * The default is null, which means this GraphObject will obey the default shadow rules (see {@link Part.isShadowed}). * * A value of true or false will ensure that this part is shadowed or not regardless of the default shadow rules, * but this GraphObject's shadowed status will not affect other GraphObjects in the Part. * * Typically this property does not need to be set, but you may need to set this value to false * on GraphObjects inside a Part that you do not wish to be shadowed. * @see {@link Part.isShadowed} */ get shadowVisible(): boolean | null; set shadowVisible(value: boolean | null); /** * This predicate is true if this object is an element, perhaps indirectly, * of the given panel. * * For example, if this GraphObject is inside a Part but is not itself the Part, * `obj.isContainedBy(obj.part)` should be true. * @param panel * @returns true if this object is contained by the given panel, * or if it is contained by another panel that is contained by the given panel, * to any depth; false if the argument is null or is not a {@link Panel}. */ isContainedBy(panel: GraphObject): boolean; /** * This predicate is true if this object is {@link visible} * and each of its visual containing panels is also visible. * This ignores the actual location or appearance (except visibility) * of the panel that this object is part of, as well as ignoring all * properties of the {@link Layer} or {@link Diagram}. * * For {@link Part}s, you can call the {@link Part.isVisible} predicate to determine * if not only the Part is visible but also any containing {@link Group} or {@link Link} or {@link Layer}. */ isVisibleObject(): boolean; /** * This predicate is false if this object is inside any Panel that is not {@link Panel.isEnabled}, * or if this is itself a disabled panel. * This ignores the {@link visible} and {@link pickable} properties. * @see {@link enabledChanged} * @see {@link Panel.isEnabled} */ isEnabledObject(): boolean; /** * Gets or sets the function to execute when some containing Panel changes the value of {@link Panel.isEnabled}. * It is typically used to modify the appearance of the object. * This function must not change the value of any panel {@link Panel.isEnabled}. * * If this property value is a function, it is called with two arguments, * this {@link GraphObject} and the new value. * By default this property is null -- no function is called. * @see {@link isEnabledObject} * @see {@link Panel.isEnabled} */ get enabledChanged(): ((thisObj: GraphObject, enabled: boolean) => void) | null; set enabledChanged(value: ((thisObj: GraphObject, enabled: boolean) => void) | null); /** * Gets or sets the orientation of a GraphObject that is in a {@link Link} or {@link Panel.Graduated}. * This controls the automatic rotation of the object by the Link Panel or Graduated Panel. * The only accepted values are the {@link Link} "Orient..." values of Link * and the default value: {@link Orientation.None}. * * When the value is {@link Orientation.None}, the {@link angle} of this object is unchanged as the link is routed. * Setting this to a value of {@link Orientation.Along} will cause routing to set the {@link angle} * to be the angle of the segment that this object is on. * Other values compute the angle somewhat differently. * If the value is changed back to {@link Orientation.None}, the {@link angle} of this object is set to zero. * * Note that when this property is not {@link Orientation.None}, this property takes precedence * over any setting or binding of the {@link angle} property. * Changes to the angle caused by orientation might not result in Changed events, * and any original value for the angle may be lost. * * In the case of Graduated Panels, if this value is {@link Orientation.None}, {@link Orientation.Along}, or {@link Orientation.Upright}, * any TextBlock label {@link angle} will be respected. Depending on this value, the effective TextBlock angle will be either * fixed or relative to the slope of the path where it is rendered. * * For examples of how to use this property, see Link Labels. * @see {@link segmentFraction} * @see {@link segmentIndex} * @see {@link segmentOffset} */ get segmentOrientation(): Orientation; set segmentOrientation(value: Orientation); /** * Gets or sets the segment index of a GraphObject that is in a {@link Link}. * Non-negative numbers count up from zero, which is the first segment, at the "from" end of the Link. * Negative numbers count segments from the "to" end of the Link, where -1 means the last segment * and -2 means the next-to-last segment. * The default value is -Infinity. The value should be an integer or NaN. * * Setting this value to NaN means {@link segmentFraction}'s fractional distance will be calculated along the entire link route. * A NaN value also means the {@link Link.midPoint} and {@link Link.midAngle} will not be used when determining label positions. * * If you do not set this property, the Link will choose a place that is approximately at the * mid-point of the link's route. * * For examples of how to use this property, see Link Labels. * @see {@link segmentFraction} * @see {@link segmentOffset} * @see {@link segmentOrientation} */ get segmentIndex(): number; set segmentIndex(value: number); /** * Gets or sets the fractional distance along a segment of a GraphObject that is in a {@link Link}. * The value should be between zero and one, where zero is at the point at the start of the segment, * and where one is at the point at the end of the segment. * The default value is zero. * * If {@link segmentIndex} is set to NaN, the fractional distance will be calculated along the entire link route. * * For examples of how to use this property, see Link Labels. * @see {@link segmentIndex} * @see {@link segmentOffset} * @see {@link segmentOrientation} */ get segmentFraction(): number; set segmentFraction(value: number); /** * Gets or sets the offset of a GraphObject that is in a {@link Link} from a point on a segment * or in a {@link Panel.Graduated} from a point along the main element. * The X component of the Point indicates the distance along the route, * with positive values going further toward the "to" end of the link or panel. * The Y component of the Point indicates the distance away from the route, * with positive values towards the right as seen when facing further towards the "to" end of the link or panel. * The value defaults to the Point (0, 0). * You cannot modify the x or y of the value of this property -- * if you want to change the segmentOffset you must set this property to a different Point. * * For labels that are near either end of a link, it may be convenient to set the segmentOffset * to Point(NaN, NaN). This causes the offset to be half the width and half the height of the label object. * * For examples of how to use this property, see Link Labels. * @see {@link segmentFraction} * @see {@link segmentIndex} * @see {@link segmentOrientation} */ get segmentOffset(): Point; set segmentOffset(value: Point); /** * Gets or sets the stretch of the GraphObject. * This controls whether the width and/or height of this object automatically adjusts to fill * the area allotted by the containing Panel. * * The only accepted values are listed as constant properties of GraphObject, * such as {@link Stretch.None}, {@link Stretch.Fill}, {@link Stretch.Horizontal}, or {@link Stretch.Vertical}. * The default value is {@link Stretch.Default}, which allows the Panel to decide how to treat this object, depending on the type of Panel. * * Objects with an {@link angle} that are stretched may look incorrect unless the angle is a multiple of 90. * * Stretch will have have different effects based upon the Panel containing this object. Elements of: * - Auto panels will not stretch, except the main element growing to fill the panel or being made uniform * - Horizontal panels will only stretch vertically * - Vertical panels will only stretch horizontally * - Spot panels will stretch to the size of the main element * - Table panels will stretch to the size of their cell, defined by their row and column, which is usually determined by other GraphObjects in that cell that are not stretching * - Grid panels, Link panels, and Graduated panels will not stretch * @see {@link Panel.defaultStretch} * @see {@link desiredSize} * @see {@link minSize} * @see {@link maxSize} * @see {@link measuredBounds} * @see {@link actualBounds} * @see {@link scale} * @see {@link Picture.imageStretch} */ get stretch(): Stretch; set stretch(value: Stretch); /** * Gets or sets the name for this object. * The default value is the empty string. * The name should be unique within a {@link Panel}, although if it isn't, * it reduces the usefulness of methods such as {@link Panel.findObject}. * * You must not modify the name of a GraphObject once it is in the visual tree of a Part. * * This is frequently needed to identify a particular GraphObject in the visual tree of a Part, * for example as the value of the {@link Part.locationObjectName} or * {@link Part.selectionObjectName} properties. */ get name(): string; set name(value: string); /** * Gets or sets the multiplicative opacity for this GraphObject and (if a Panel) all elements. * The value must be between 0.0 (fully transparent) and 1.0 (no additional transparency). * * Unlike {@link visible}, Opacity only affects drawing, it does not cause objects to be resized or remeasured. * Opacity settings do not change the shape of the object or exclude it from object-picking * (does not change whether any objects are found by the "find..." methods). * * This value is multiplicative with any existing transparency, * for instance from {@link Layer.opacity} or a GraphObject's opacity higher in the visual tree, * or from a {@link Brush} or image transparency. * The default value is 1. * @see {@link visible} * @see {@link pickable} * @see {@link Layer.opacity} * @see {@link Diagram.opacity} */ get opacity(): number; set opacity(value: number); /** * Undocumented. May not work in Safari. */ get filter(): string; /** * Undocumented. May not work in Safari. */ set filter(value: string); /** * Gets or sets whether a GraphObject is visible. * The default value is true. * A not visible object takes no space in the Panel that it is in. * Toggling visibility may cause elements in the visual tree to re-measure and re-arrange. * Making a Panel not visible causes all of its elements not to be seen or receive input events. * Changing a Panel to become visible causes all of its elements to be seen and be active, * unless those elements are themselves not visible. * * This object does not get any mouse/touch events if it is not {@link visible} * or if it is not {@link pickable}. * * One can have a visible {@link Shape} that is not drawn by setting its {@link Shape.fill} * and {@link Shape.stroke} to null or to `"transparent"`. * Similarly, one can set {@link TextBlock.stroke} to null or to `"transparent"`. * It is also possible make a GraphObjects transparent by setting {@link GraphObject.opacity} to 0. * Finally, one can make a whole {@link Layer}-full of Parts invisible by setting {@link Layer.visible} to false. * * Use the {@link isVisibleObject} predicate to see if this GraphObject is visible and is inside a {@link Panel} * that is {@link isVisibleObject}, and so forth up the chain of panels until reaching the {@link Part}. * * For {@link Part}s, you can call the {@link Part.isVisible} predicate to determine * if not only the Part is visible but also any containing {@link Group} or {@link Link}, * and whether the {@link Layer} it is in is visible. * @see {@link opacity} * @see {@link pickable} * @see {@link Layer.visible} */ get visible(): boolean; set visible(value: boolean); /** * Gets or sets whether or not this GraphObject can be chosen by visual "find" or "hit-test" methods such * as {@link Diagram.findObjectAt}. * * This object does not get any mouse/touch events if it is not {@link visible} * or if it is not {@link pickable}. * * The default value is true -- mouse events on this object will be noticed. * If this value is false and this object is a {@link Panel}, not only is this Panel not "hittable", * but all of the elements inside the Panel will be ignored. * @see {@link visible} * @see {@link opacity} * @see {@link Layer.pickable} * @see {@link Panel.isEnabled} */ get pickable(): boolean; set pickable(value: boolean); /** * Gets or sets whether the user may draw duplicate Links from this port. * This property is used by {@link LinkingBaseTool.isValidLink}. * The default value is false. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link fromLinkable} * @see {@link fromLinkableSelfNode} * @see {@link toLinkableDuplicates} */ get fromLinkableDuplicates(): boolean; set fromLinkableDuplicates(value: boolean); /** * Gets or sets whether the user may draw Links that connect from this port's Node. * This property is used by {@link LinkingBaseTool.isValidLink}. * The default value is false. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link fromLinkable} * @see {@link fromLinkableDuplicates} * @see {@link toLinkableSelfNode} */ get fromLinkableSelfNode(): boolean; set fromLinkableSelfNode(value: boolean); /** * Gets or sets whether the user may draw duplicate Links to this port. * This property is used by {@link LinkingBaseTool.isValidLink}. * The default value is false. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link toLinkable} * @see {@link toLinkableSelfNode} * @see {@link fromLinkableDuplicates} */ get toLinkableDuplicates(): boolean; set toLinkableDuplicates(value: boolean); /** * Gets or sets whether the user may draw Links that connect to this port's Node. * This property is used by {@link LinkingBaseTool.isValidLink}. * The default value is false. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link toLinkable} * @see {@link toLinkableDuplicates} * @see {@link fromLinkableSelfNode} */ get toLinkableSelfNode(): boolean; set toLinkableSelfNode(value: boolean); /** * Gets or sets whether a GraphObject is the "main" object for some types of {@link Panel}. * Panels that use a "main" object include {@link Panel.Auto}, {@link Panel.Spot}, and {@link Panel.Link}. * * Panels that use a "main" object will use the first object that has this property set to true, * or else just the first object, if none have the property set. * * Do not modify this property once this object is an element of a panel. */ get isPanelMain(): boolean; set isPanelMain(value: boolean); /** * This property determines whether or not this GraphObject's events occur * before all other events, including selection. This enables the {@link actionDown}, * {@link actionMove}, {@link actionUp}, and {@link actionCancel} events, * which are all handled by the {@link ActionTool}. * * This object does not get any mouse/touch events if it is not {@link visible} * or if it is not {@link pickable}. * * This property is infrequently used -- typically only when implementing objects * that act as buttons or knobs or sliders. * The default value is false. * @see {@link actionDown} * @see {@link actionMove} * @see {@link actionUp} * @see {@link actionCancel} * @see {@link pickable} * @see {@link Panel.isEnabled} */ get isActionable(): boolean; set isActionable(value: boolean); /** * Gets or sets the background Brush of this GraphObject, * filling the rectangle of this object's local coordinate space. * If the object is rotated, the background will rotate with it. * * The value may be either a {@link Brush} object or a string that is a CSS color. * The default value is null -- no background is drawn. * More information about the syntax of CSS color strings is available at: * CSS colors (mozilla.org). * @see {@link Shape.fill} */ get background(): BrushLike; set background(value: BrushLike); /** * This read-only property returns the {@link Part} containing this object, if any. * The Part will be the root GraphObject in this GraphObject's visual tree. * * It is common to refer to the containing Part of a GraphObject * in order to refer to the {@link Panel.data} to which it is bound. * * This property is not settable. * If you want this GraphObject to belong to a Part, you will need to add it to a Part, * or else add it to some visual tree structure that is added to a Part using {@link Panel.add}. * * Note that for objects such as buttons that are in {@link Adornment}s such as tooltips or context menus, * this property will return that Adornment, not the Node or Link that is adorned. * * If you want to find a {@link Group} that contains a Part, use the {@link Part.containingGroup} property: * `someObj.part.containingGroup` */ get part(): Part | null; /** * This read-only property returns the GraphObject's containing {@link Panel}, or null if this object is not in a Panel. * * Although {@link Part} inherits from this class, a Part will never belong to a Panel, * so this property will always be null for every {@link Node} or {@link Link}. * * This property is not settable. * Instead, call {@link Panel.add} in order to put a GraphObject in a Panel. */ get panel(): Panel | null; /** * This read-only property returns the GraphObject's containing {@link Layer}, if there is any. * A plain GraphObject cannot belong directly to a Layer -- only a {@link Part} can belong directly to a Layer. * * This property is not settable. * Normally one changes which Layer that a GraphObject is in by setting {@link Part.layerName}. * Adding a Part to a Diagram will automatically add that Part to a Layer in that Diagram based on the layerName. */ get layer(): Layer | null; /** * This read-only property returns the {@link Diagram} that this GraphObject is in, if it is. * * This property is not settable. * Although you cannot add any plain GraphObject to a Diagram, you can call {@link Diagram.add} * to add a {@link Part} to a Diagram. */ get diagram(): Diagram | null; /** * Gets or sets the position of this GraphObject in container coordinates * (either a {@link Panel} or the document). * Value must be of type Point. * You cannot modify the x or y of the value of this property -- * if you want to change the position you must set this property to a different Point. * Default is `Point(NaN, NaN)`. * * For {@link Part}s, see also {@link Part.location}. */ get position(): Point; set position(value: Point); /** * This read-only property returns the bounds of this GraphObject in container coordinates. This means that * the actualBounds are in the coordinate space of the GraphObject's {@link Panel}, * unless this is a {@link Part}, in which case they are in * the {@link Diagram}'s coordinate system. * * You must not modify any of the properties of the {@link Rect} that is the value of this property. * * If this GraphObject is a Part, * then the x and y values of the actualBounds are identical to that Part's {@link position}, * and the width and height values of the actualBounds represent the rectangular space occupied * by the Part in {@link Diagram.documentBounds} coordinates. * * If this GraphObject is not a top-level object (not a {@link Part}), then the actualBounds * x and y values represent that GraphObject's position within its Panel. In a Panel of type {@link Panel.Position} * this is identical to the GraphObject's {@link position}, but in other cases it is dependent on * the unique workings of each Panel type. The actualBounds width and height * of a GraphObject are the final size after the {@link scale} and {@link angle} are applied. * * It is possible for a GraphObject (be it an GraphObject or a Panel containing several more GraphObjects) * to have no containing Part, in which case these GraphObjects cannot possibly be in a Diagram. * These GraphObjects are unlikely to have real-number values for their actualBounds, as they may * never have had the chance to be measured and arranged. * * As with all read-only properties, using this property as a binding source is unlikely to be useful. * @see {@link measuredBounds} * @see {@link desiredSize} */ get actualBounds(): Rect; /** * Gets or sets the scale transform of this GraphObject. * Value must be a number; larger values will make this object appear bigger. * Default is 1. * @see {@link angle} * @see {@link stretch} */ get scale(): number; set scale(value: number); /** * Gets or sets the angle transform, in degrees, of this GraphObject. * Value must be a number. If the value is not between (0 <= value < 360), * it will be normalized to be in that range. * Zero is along the positive X-axis (rightwards); 90 is along the positive Y-axis (downwards). * Default is 0. * * When set on a Graduated Panel's TextBlock label, this value will be be ignored if {@link segmentOrientation} is not * {@link Orientation.None}, {@link Orientation.Along}, or {@link Orientation.Upright}. OrientAlong and OrientUpright will use this angle * relative to the slope of the main path. * * When set on a Link label, this value will be be ignored if {@link segmentOrientation} is not {@link Orientation.None}. * @see {@link scale} * @see {@link stretch} */ get angle(): number; set angle(value: number); /** * Gets or sets the desired size of this GraphObject in local coordinates. * Value must be of type {@link Size}. * Default is Size(NaN, NaN). * You cannot modify the width or height of the value of this property -- * if you want to change the desiredSize you must set this property to a different Size. * * Getting or setting {@link width} or {@link height} is equivalent to getting or setting the * width or height of this property. * * The size does not include any transformation due to {@link scale} or {@link angle}, * nor any pen thickness due to {@link Shape.strokeWidth} if this is a {@link Shape}. * If there is a containing {@link Panel} the Panel will determine the actual size. * If the desiredSize is greater than the allowed size that the GraphObject's Panel determines, * then the GraphObject may be visually clipped. If the desiredSize does not meet the constraints * of {@link minSize} and {@link maxSize}, the GraphObject will be resized to meet them. * @see {@link minSize} * @see {@link maxSize} * @see {@link naturalBounds} * @see {@link measuredBounds} * @see {@link actualBounds} */ get desiredSize(): Size; set desiredSize(value: Size); /** * Gets or sets the desired width of this GraphObject in local coordinates. * This just gets or sets the width component of the {@link desiredSize}. * Default is NaN. * * Size can also be constrained by setting {@link minSize} and {@link maxSize}. * * The width does not include any transformation due to {@link scale} or {@link angle}, * nor any pen thickness due to {@link Shape.strokeWidth} if this is a {@link Shape}. * If there is a containing {@link Panel} the Panel will determine the actual size. */ get width(): number; set width(value: number); /** * Gets or sets the desired height of this GraphObject in local coordinates. * This just gets or sets the height component of the {@link desiredSize}. * Default is NaN. * * Size can also be constrained by setting {@link minSize} and {@link maxSize}. * * The height does not include any transformation due to {@link scale} or {@link angle}, * nor any pen thickness due to {@link Shape.strokeWidth} if this is a {@link Shape}. * If there is a containing {@link Panel} the Panel will determine the actual size. */ get height(): number; set height(value: number); /** * Gets or sets the minimum size of this GraphObject in container coordinates * (either a {@link Panel} or the document). * Any new value must be of type Size; NaN values are treated as 0. * * You cannot modify the width or height of the value of this property -- * if you want to change the minSize you must set this property to a different Size. * The default value is zero by zero. * A containing Panel will determine the actual size of this object. * @see {@link maxSize} * @see {@link desiredSize} */ get minSize(): Size; set minSize(value: Size); /** * Gets or sets the maximum size of this GraphObject in container coordinates * (either a {@link Panel} or the document). * Any new value must be of type Size; NaN values are treated as Infinity. If you want no maximum width or height, use NaN or Infinity. * * You cannot modify the width or height of the value of this property -- * if you want to change the maxSize you must set this property to a different Size. * The default value is Infinity by Infinity. * A containing Panel will determine the actual size of this object. * @see {@link minSize} * @see {@link desiredSize} */ get maxSize(): Size; set maxSize(value: Size); /** * This read-only property returns the measuredBounds of the GraphObject in container coordinates * (either a {@link Panel} or the document). * This describes the transformed bounds with margins excluded. * * You must not modify any of the properties of the {@link Rect} that is the value of this property. * * As with all read-only properties, using this property as a binding source is unlikely to be useful. * @see {@link naturalBounds} * @see {@link desiredSize} * @see {@link actualBounds} */ get measuredBounds(): Rect; /** * This read-only property returns the natural bounding rectangle of this GraphObject in local coordinates, * before any transformation by {@link scale} or {@link angle}. * Defaults to unknown (NaN,NaN). * * You must not modify any of the properties of the {@link Rect} that is the value of this property. * * The value can only be changed by changing properties of the particular GraphObject, * such as {@link GraphObject.desiredSize}, {@link Shape.geometry}, or {@link TextBlock.font}. * * As with all read-only properties, using this property as a binding source is unlikely to be useful. * @see {@link desiredSize} * @see {@link measuredBounds} * @see {@link actualBounds} */ get naturalBounds(): Rect; /** * Gets or sets the size of empty area around this GraphObject, as a {@link Margin}, * in the containing {@link Panel} coordinates. * * Negative values are permitted but may cause overlaps with adjacent * objects in a {@link Panel}. * You cannot modify the top or left or right or bottom of the value of this property -- * if you want to change the margin you must set this property to a different Margin. * Default margin is `Margin(0,0,0,0)`. * * For most uses, increasing a margin will increase the space this GraphObject takes in its containing panel. * When an object has a {@link GraphObject.stretch} value applied, margins may decrease the size of that object. * * The property setter accepts a number instead of a Margin object: providing a * number `N` will result in using a `Margin(N, N, N, N)`. * The property getter will always return a Margin. * @see {@link desiredSize} * @see {@link measuredBounds} * @see {@link actualBounds} * @see {@link Panel.padding} */ get margin(): MarginLike; set margin(value: MarginLike); /** * Add an {@link AnimationTrigger} to this GraphObject for the given property name and optional animation settings. * @param propertyName - A string naming the target property to animate. * This should not be the empty string. * @param animationSettings - An optional Object describing properties to set on animations created by this AnimationTrigger. * See the {@link AnimationTrigger.animationSettings} property for detail. * If specified, this also sets the {@link AnimationTrigger.startCondition} to {@link TriggerStart.Immediate}. * @param startCondition - An optional TriggerStart to set the {@link AnimationTrigger.startCondition} property. * @returns this GraphObject * @since 3.0 */ trigger(propertyName: string, animationSettings?: { duration?: number; finished?: (animation: Animation) => void; easing?: EasingFunction; }, startCondition?: TriggerStart): this; /** * Add an {@link AnimationTrigger} to this GraphObject. * @param trigger - an AnimationTrigger * @returns this GraphObject * @since 2.2 */ trigger(trigger: AnimationTrigger): this; /********************************************************** Panel-specific properties: ***********************************************************/ /** * Gets or sets the alignment {@link Spot} of this GraphObject used in {@link Panel} layouts, * to determine where in the area allocated by the panel this object should be placed. * * The default value is {@link Spot.Default}, which lets the Panel determine the Spot using * {@link Panel.defaultAlignment}. If that property is also {@link Spot.Default}, * then the alignment spot will be different depending on the Panel type. * * The {@link alignmentFocus} is often used along with this property to specify * where this object should be positioned in a Panel. * * A {@link Spot.Default} is equivalent to Spot.Center in Spot, Auto, Horizontal, and Vertical panels. * For examples of alignments in different panels, see the Introduction page on Panels. * * @see {@link alignmentFocus} * @see {@link Panel.defaultAlignment} */ get alignment(): Spot; set alignment(value: Spot); /** * Gets or sets the column of this GraphObject if it is in a Table {@link Panel}. * The value must be a small non-negative integer. The default is 0. */ get column(): number; set column(value: number); /** * Gets or sets the number of columns spanned by this GraphObject if it is in a Table {@link Panel}. * The value must be a small positive integer. The default is 1. */ get columnSpan(): number; set columnSpan(value: number); /** * Gets or sets the row of this GraphObject if it is in a Table {@link Panel}. * The value must be a small non-negative integer. The default is 0. */ get row(): number; set row(value: number); /** * Gets or sets the number of rows spanned by this GraphObject if it is in a Table {@link Panel}. * The value must be a small positive integer. The default is 1. */ get rowSpan(): number; set rowSpan(value: number); /** * (undocumented) */ get spanAllocation(): ((a: GraphObject, b: RowColumnDefinition, c: number) => number) | null; set spanAllocation(value: ((a: GraphObject, b: RowColumnDefinition, c: number) => number) | null); /** * Gets or sets the spot on this GraphObject to be used as the alignment point * in Spot and Fixed {@link Panel}s. * Value must be of the Spot. * * The default value is {@link Spot.Default}, which means that the Panel type can decide the effective alignment spot. * * The {@link alignment} is often used along with this property to specify * where this object should be positioned in a Panel. * * For {@link Panel.Graduated}, the alignmentFocus spot determines the spot on a child element to be aligned with some * point along the main element. * * When you want a link label Node to be positioned by its location spot rather than by this alignmentFocus spot, * you can set this property to {@link Spot.None}, only on {@link Node}s. * * For examples of alignments in different panels, see the Introduction page on Panels. * @see {@link Panel.alignmentFocusName} */ get alignmentFocus(): Spot; set alignmentFocus(value: Spot); /********************************************************** Port-specific properties: ***********************************************************/ /** * Gets or sets an identifier for an object acting as a port on a Node. * The default value is null -- this object is not a port. * * A value that is the empty string is used by convention to mean the primary * (and usually only) port of the node. * * If a Node has no named ports, then the Node itself is the sole port. * * Note: the only kind of model that can save port information, i.e. portIds that are not an empty string, * for links is a {@link GraphLinksModel} whose {@link GraphLinksModel.linkFromPortIdProperty} and * {@link GraphLinksModel.linkToPortIdProperty} have been set to name properties on the link data objects. * * The value should be unique within the {@link Node}. * You must not modify this property once this GraphObject is in the visual tree of a Node. *

* See the Introduction page on ports * for usage information and examples. * @see {@link fromLinkable} * @see {@link toLinkable} * @see {@link fromSpot} * @see {@link toSpot} * @see {@link Link.fromSpot} * @see {@link Link.toSpot} */ get portId(): string; set portId(value: string); /** * Gets or sets where a link should connect to this port. * The default value is {@link Spot.None}, meaning that the link routing * must consider the shape of the port and connect to the closest point. * * The value of {@link Link.toSpot}, if not {@link Spot.Default}, takes precedence over the value at this port * when determining the route of the link. * A number of the predefined {@link Layout}s automatically set {@link Link.fromSpot} and {@link Link.toSpot}, * thereby causing this property and {@link fromSpot} on the port element to be ignored. * Depending on the layout, you may be able to disable that behavior, such as by setting {@link ForceDirectedLayout.setsPortSpots}, * {@link TreeLayout.setsPortSpot}, {@link TreeLayout.setsChildPortSpot}, or {@link LayeredDigraphLayout.setsPortSpots} to false. * * For examples of how to use this property, see Link Connection Points. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link Link.toSpot} * @see {@link Link.computeSpot} * @see {@link fromSpot} * @see {@link portId} */ get toSpot(): Spot; set toSpot(value: Spot); /** * Gets or sets the length of the last segment of a link going to this port. * This value is used when the computed "to spot" is not {@link Spot.None}. * The default value is 10. * * The value of {@link Link.toEndSegmentLength}, if not NaN, takes precedence over the value at this port * when determining the route of the link. * This value also limits how short the {@link Link.toShortLength} may be drawn. * * For examples of how to use this property, see Link End Segment Lengths. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link Link.toEndSegmentLength} * @see {@link Link.computeEndSegmentLength} * @see {@link fromEndSegmentLength} * @see {@link portId} */ get toEndSegmentLength(): number; set toEndSegmentLength(value: number); /** * Gets or sets how far the end segment of a link going to this port stops short of the actual port. * Positive values are limited by the {@link toEndSegmentLength} or {@link Link.toEndSegmentLength}. * Negative values cause the link to extend into the port. * The default value is zero. * * This property is useful when you have a thick link and a pointy arrowhead. * Normally the link Shape extends all the way to the end of the arrowhead. * If the link Shape is wide, its edges will be seen behind the arrowhead. * By setting this property to a small positive value, the link Shape can end within the * body of the arrowhead, leaving only the point of the arrowhead visible at the end of the link. * * A negative value for this property can also be useful when you want the link Shape to continue * into the port, perhaps because a portion of the port is transparent and you want the link to * appear to connect visually with a different point on the node. * * The value of {@link Link.toShortLength}, if not NaN, takes precedence over the value at this port * when determining the route of the link. * * For examples of how to use this property, see Link Connection Points. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link fromShortLength} * @see {@link Link.toShortLength} * @see {@link portId} */ get toShortLength(): number; set toShortLength(value: number); /** * Gets or sets whether the user may draw Links to this port. * This property is used by {@link LinkingBaseTool.isValidTo}. * * The default value is null, which indicates that the real value is inherited from * the parent {@link Panel}, or false if there is no containing panel. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node, * or unless you are disabling the "linkability" of a particular GraphObject * inside a Panel whose toLinkable has been set or bound to true. * @see {@link fromLinkable} * @see {@link toMaxLinks} * @see {@link portId} * @see {@link cursor} */ get toLinkable(): boolean | null; set toLinkable(value: boolean | null); /** * Gets or sets the maximum number of links that may go into this port. * This property is used by {@link LinkingBaseTool.isValidTo}. * * The value must be non-negative. * The default value is Infinity. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link toLinkable} * @see {@link fromMaxLinks} * @see {@link portId} */ get toMaxLinks(): number; set toMaxLinks(value: number); /** * Gets or sets where a link should connect from this port. * The default value is {@link Spot.None}, meaning that the link routing * must consider the shape of the port and connect at the closest point. * * The value of {@link Link.fromSpot}, if not {@link Spot.Default}, takes precedence over the value at this port * when determining the route of the link. * A number of the predefined {@link Layout}s automatically set {@link Link.fromSpot} and {@link Link.toSpot}, * thereby causing this property and {@link toSpot} on the port element to be ignored. * Depending on the layout, you may be able to disable that behavior, such as by setting {@link ForceDirectedLayout.setsPortSpots}, * {@link TreeLayout.setsPortSpot}, {@link TreeLayout.setsChildPortSpot}, or {@link LayeredDigraphLayout.setsPortSpots} to false. * * For examples of how to use this property, see Link Connection Points. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link Link.fromSpot} * @see {@link Link.computeSpot} * @see {@link toSpot} * @see {@link portId} */ get fromSpot(): Spot; set fromSpot(value: Spot); /** * Gets or sets the length of the first segment of a link coming from this port. * This value is used when the computed "from spot" is not {@link Spot.None}. * The default value is 10. * This value also limits how short the {@link Link.fromShortLength} may be drawn. * * The value of {@link Link.fromEndSegmentLength}, if not NaN, takes precedence over the value at this port * when determining the route of the link. * * For examples of how to use this property, see Link End Segment Lengths. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link Link.fromEndSegmentLength} * @see {@link Link.computeEndSegmentLength} * @see {@link toEndSegmentLength} * @see {@link portId} */ get fromEndSegmentLength(): number; set fromEndSegmentLength(value: number); /** * Gets or sets how far the end segment of a link coming from this port stops short of the actual port. * Positive values are limited by the {@link fromEndSegmentLength} or {@link Link.fromEndSegmentLength}. * Negative values cause the link to extend into the port. * The default value is zero. * * This property is useful when you have a thick link and a pointy arrowhead. * Normally the link Shape extends all the way to the end of the arrowhead. * If the link Shape is wide, its edges will be seen behind the arrowhead. * By setting this property to a small positive value, the link Shape can end within the * body of the arrowhead, leaving only the point of the arrowhead visible at the end of the link. * * A negative value for this property can also be useful when you want the link Shape to continue * into the port, perhaps because a portion of the port is transparent and you want the link to * appear to connect visually with a different point on the node. * * The value of {@link Link.fromShortLength}, if not NaN, takes precedence over the value at this port * when determining the route of the link. * * For examples of how to use this property, see Link Connection Points. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link toShortLength} * @see {@link Link.fromShortLength} * @see {@link portId} */ get fromShortLength(): number; set fromShortLength(value: number); /** * Gets or sets whether the user may draw Links from this port. * This property is used by {@link LinkingBaseTool.isValidFrom}. * * The default value is null, which indicates that the real value is inherited from * the parent {@link Panel}, or false if there is no containing panel. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node, * or unless you are disabling the "linkability" of a particular GraphObject * inside a Panel whose fromLinkable has been set or bound to true. * @see {@link toLinkable} * @see {@link fromMaxLinks} * @see {@link portId} * @see {@link cursor} */ get fromLinkable(): boolean | null; set fromLinkable(value: boolean | null); /** * Gets or sets the maximum number of links that may come out of this port. * This property is used by {@link LinkingBaseTool.isValidFrom}. * * The value must be non-negative. * The default value is Infinity. * * You must set this property on a GraphObject whose {@link portId} is non-null, * unless the whole {@link Node} is acting as a single port, * in which case this property should be set on the Node. * @see {@link fromLinkable} * @see {@link toMaxLinks} * @see {@link portId} */ get fromMaxLinks(): number; set fromMaxLinks(value: number); /********************************************************** Event Handling: ***********************************************************/ /** * Gets or sets the mouse cursor to use when the mouse is over this object with no mouse buttons pressed. * The value is the empty string when no particular cursor is specified for this object; * the actual cursor is determined by any containing {@link Panel}. * * The default value is the empty string, which means the * current mouse cursor is determined by the Diagram. * Other strings should be valid CSS strings that specify a cursor. * This provides some more information about cursor syntax: * CSS cursors (mozilla.org). * * Read more about cursors at {@link Diagram.currentCursor} * @see {@link Diagram.defaultCursor} * @see {@link Diagram.currentCursor} */ get cursor(): string; set cursor(value: string); /** * Gets or sets the function to execute when the user single-primary-clicks on this object. * This typically involves a mouse-down followed by a prompt mouse-up * at approximately the same position using the left (primary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on a {@link GraphObject}. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name `"ObjectSingleClicked"`. * * If this property value is a function, it is called with an {@link InputEvent} * and this {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * * From the second argument, *obj*, you can get to the Node or Link via the {@link part} property. * From there you can access the bound data via the {@link Panel.data} property. * So from an event handler you can get the bound data by `obj.part.data`. * * By default this property is null. * * Objects in Layers that are {@link Layer.isTemporary} do not receive click events. * If you do want such objects to respond to clicks, set {@link isActionable} to true. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. *

* An example of a click event handler is shown in the * Arrowheads sample. * @see {@link doubleClick} * @see {@link contextClick} * @see {@link Diagram.click} */ get click(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set click(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user double-primary-clicks on this object. * This typically involves a mouse-down/up/down/up in rapid succession * at approximately the same position using the left (primary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on a {@link GraphObject}. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name `"ObjectDoubleClicked"`. * * If this property value is a function, it is called with an {@link InputEvent} * and this {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * * From the second argument, *obj*, you can get to the Node or Link via the {@link part} property. * From there you can access the bound data via the {@link Panel.data} property. * So from an event handler you can get the bound data by `obj.part.data`. * * By default this property is null. * * Objects in Layers that are {@link Layer.isTemporary} do not receive click events. * If you do want such objects to respond to clicks, set {@link isActionable} to true. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. * * The Class Hierarchy sample * demonstrates the definition of a double-click event handler that opens up * a web page with the documentation for that class: * ```js * diagram.nodeTemplate = * new go.Node(..., * { * doubleClick: // here the second argument is this object, which is this Node * (e, node) => { window.open("../api/symbols/" + node.data.key + ".html"); } * }).add( * // elements for Node... * ) * ``` * @see {@link click} * @see {@link contextClick} * @see {@link Diagram.doubleClick} */ get doubleClick(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set doubleClick(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user single-secondary-clicks on this object. * This typically involves a mouse-down followed by a prompt mouse-up * at approximately the same position using the right (secondary) mouse button. * This property is used by the {@link ClickSelectingTool} * when the user clicks on a {@link GraphObject}. * The function is called in addition to the {@link DiagramEvent} * that is raised with the name `"ObjectContextClicked"`. * * If this property value is a function, it is called with an {@link InputEvent} * and this {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * * From the second argument, *obj*, you can get to the Node or Link via the {@link part} property. * From there you can access the bound data via the {@link Panel.data} property. * So from an event handler you can get the bound data by `obj.part.data`. * * By default this property is null. * * Objects in Layers that are {@link Layer.isTemporary} do not receive click events. * If you do want such objects to respond to clicks, set {@link isActionable} to true. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. * @see {@link click} * @see {@link doubleClick} * @see {@link Diagram.contextClick} */ get contextClick(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set contextClick(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse * into this object without holding down any buttons. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}, * this {@link GraphObject} that the mouse is now in, * and any previous {@link GraphObject} that the mouse was in. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * By default this property is null. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * After calling this function the diagram will be updated immediately. * * For example, consider the situation where one wants to display buttons that the user can click * whenever the user passes the mouse over a node, and the buttons automatically disappear when the * mouse leaves the node. This can be implemented by showing an Adornment holding the buttons. * ```js * const nodeContextMenu = * new go.Adornment("Spot", * { background: "transparent" }).add( // to help detect when the mouse leaves the area * new go.Placeholder(), * new go.Panel("Vertical", * { alignment: go.Spot.Right, alignmentFocus: go.Spot.Left }).add( * go.GraphObject.build("Button") * .add(new go.TextBlock("Command 1")) * .set({ * click: (e, obj) => { * const node = obj.part.adornedPart; * alert("Command 1 on " + node.data.text); * node.removeAdornment("ContextMenuOver"); * } * }), * go.GraphObject.build("Button") * .add(new go.TextBlock("Command 2")) * .set({ * click: (e, obj) => { * const node = obj.part.adornedPart; * alert("Command 2 on " + node.data.text); * node.removeAdornment("ContextMenuOver"); * } * }) * ) * ); * ``` * Then in the definition of the Node we can implement a mouseEnter event handler: * ```js * myDiagram.nodeTemplate = * new go.Node(..., * { * . . . * mouseEnter: (e, node) => { * nodeContextMenu.adornedObject = node; * nodeContextMenu.mouseLeave = (ev, cm) => { * node.removeAdornment("ContextMenuOver"); * } * node.addAdornment("ContextMenuOver", nodeContextMenu); * } * }).add( * // Node elements ... * ) * ``` * Note how it automatically defines a {@link mouseLeave} event handler too. * The context menu Adornment is removed either when the mouse leaves the area of the Adornment * or when the user executes a button click event handler. * @see {@link mouseLeave} * @see {@link mouseOver} * @see {@link mouseHover} * @see {@link mouseDragEnter} */ get mouseEnter(): ((e: InputEvent, thisObj: GraphObject, prevObj: GraphObject) => void) | null; set mouseEnter(value: ((e: InputEvent, thisObj: GraphObject, prevObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse * out of this object without holding down any buttons. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}, * this {@link GraphObject} that the mouse has left, * and any next {@link GraphObject} that the mouse is now in. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * By default this property is null. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * After calling this function the diagram will be updated immediately. * * For example, the Flow Chart sample * automatically shows and hides the ports as the mouse passes over a node. * The node template includes the following settings: * ```js * myDiagram.nodeTemplate = * new go.Node(..., * { * . . . * // handle mouse enter/leave events to show/hide the ports * mouseEnter: (e, obj) => showPorts(obj.part, true), * mouseLeave: (e, obj) => showPorts(obj.part, false) * . . . * }).add( * // Node elements ... * ) * ``` * where the `showPorts` function is defined to set the {@link visible} * property of each of the port elements of the node. * @see {@link mouseEnter} * @see {@link mouseOver} * @see {@link mouseHover} * @see {@link mouseDragLeave} */ get mouseLeave(): ((e: InputEvent, thisObj: GraphObject, nextObj: GraphObject) => void) | null; set mouseLeave(value: ((e: InputEvent, thisObj: GraphObject, nextObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse * over this object without holding down any buttons. * This property is used by the {@link ToolManager}. * This property is infrequently used -- it is more common to implement {@link mouseEnter} * and {@link mouseLeave} functions. * * If this property value is a function, it is called with an {@link InputEvent} * and this {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * By default this property is null. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * After calling this function the diagram will be updated immediately. * @see {@link mouseHover} * @see {@link mouseEnter} * @see {@link mouseLeave} */ get mouseOver(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set mouseOver(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user holds the mouse still for a while * over this object without holding down any buttons. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. * * You can control how long the user must wait with a motionless mouse before * a "mouse hover" event occurs, by setting {@link ToolManager.hoverDelay}. * For example: * ```js * myDiagram = new go.Diagram("myDiagramDiv", * { "toolManager.hoverDelay": 500 }); // 500 milliseconds * ``` * or: * ```js * myDiagram.toolManager.hoverDelay = 500; // 500 milliseconds * ``` * @see {@link mouseOver} * @see {@link mouseEnter} * @see {@link mouseLeave} */ get mouseHover(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set mouseHover(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user holds the mouse still for a while * over this object while holding down a button. * This property is used by the {@link ToolManager}. * * If this property value is a function, it is called with an {@link InputEvent}. * By default this property is null. * * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. * * You can control how long the user must wait during a drag with a motionless mouse before * a "mouse hold" event occurs, by setting {@link ToolManager.holdDelay}. * For example: * ```js * myDiagram = new go.Diagram("myDiagramDiv", * { "toolManager.holdDelay": 500 }); // 500 milliseconds * ``` * or: * ```js * myDiagram.toolManager.holdDelay = 500; // 500 milliseconds * ``` * @see {@link mouseDragEnter} * @see {@link mouseDragLeave} * @see {@link mouseHover} */ get mouseHold(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set mouseHold(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse * into this stationary object during a {@link DraggingTool} drag; * this allows you to provide feedback during a drag based on where it might drop. * * If this property value is a function, it is called with an {@link InputEvent}, * this {@link GraphObject}, and any previous {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * By default this property is null. * * Note that for a drag-and-drop that originates in a different diagram, the target diagram's * selection collection will not be the parts that are being dragged. * Instead the temporary parts being dragged can be found as the source diagram's {@link DraggingTool.copiedParts}. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function, * because the {@link DraggingTool} will be conducting one already. * After calling this function the diagram will be updated immediately. * * For an example of a mouseDragEnter event handler, see the node template in the * Org Chart Editor sample. * @see {@link mouseDragLeave} * @see {@link mouseHold} * @see {@link mouseDrop} * @see {@link mouseEnter} * @see {@link Group.handlesDragDropForMembers} */ get mouseDragEnter(): ((e: InputEvent, thisObj: GraphObject, prevObj: GraphObject) => void) | null; set mouseDragEnter(value: ((e: InputEvent, thisObj: GraphObject, prevObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the user moves the mouse * out of this stationary object during a {@link DraggingTool} drag; * this allows you to provide feedback during a drag based on where it might drop. * * If this property value is a function, it is called with an {@link InputEvent}, * this {@link GraphObject}, and any new {@link GraphObject} that the mouse is in. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * By default this property is null. * * Note that for a drag-and-drop that originates in a different diagram, the target diagram's * selection collection will not be the parts that are being dragged. * Instead the temporary parts being dragged can be found as the source diagram's {@link DraggingTool.copiedParts}. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function, * because the {@link DraggingTool} will be conducting one already. * After calling this function the diagram will be updated immediately. * * For an example of a mouseDragLeave event handler, see the node template in the * Org Chart Editor sample. * @see {@link mouseDragEnter} * @see {@link mouseHold} * @see {@link mouseDrop} * @see {@link mouseLeave} * @see {@link Group.handlesDragDropForMembers} */ get mouseDragLeave(): ((e: InputEvent, thisObj: GraphObject, nextObj: GraphObject) => void) | null; set mouseDragLeave(value: ((e: InputEvent, thisObj: GraphObject, nextObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when a user drops the selection on this object * at the end of a {@link DraggingTool} drag; * this allows you to customize the behavior when a drop occurs on an object. * * If this property value is a function, it is called with an {@link InputEvent}, * this {@link GraphObject}. * The {@link InputEvent.targetObject} provides the GraphObject that was found * at the mouse point before looking up the visual tree of {@link GraphObject.panel}s * to get to this object. * The function is called within the transaction performed by the {@link DraggingTool}, * so you do not need to conduct one. * By default this property is null. * * For an example of a mouseDrop event handler, see the node template in the * Org Chart Editor sample. * @see {@link mouseDragEnter} * @see {@link mouseDragLeave} * @see {@link mouseHold} * @see {@link Group.handlesDragDropForMembers} */ get mouseDrop(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set mouseDrop(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute on a mouse-down event when this GraphObject's {@link isActionable} * is set to true. * This property is infrequently set. * By default this property is null. * * This functional property is only set on objects such as buttons, knobs, or sliders that want to handle all events, * in conjunction with {@link ActionTool}, pre-empting the normal tool mechanisms. * * The {@link ActionTool} does not conduct any transaction, so if this property has a value, * the function will not be called within a transaction. * @see {@link actionMove} * @see {@link actionUp} * @see {@link actionCancel} */ get actionDown(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set actionDown(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute on a mouse-move event when this GraphObject's {@link isActionable} * is set to true. * This property is infrequently set. * By default this property is null. * * This functional property is only set on objects such as buttons, knobs, or sliders that want to handle all events, * in conjunction with {@link ActionTool}, pre-empting the normal tool mechanisms. * * The {@link ActionTool} does not conduct any transaction, so if this property has a value, * the function will not be called within a transaction. * @see {@link actionDown} * @see {@link actionUp} * @see {@link actionCancel} */ get actionMove(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set actionMove(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute on a mouse-up event when this GraphObject's {@link isActionable} * is set to true. * This property is infrequently set. * By default this property is null. * * This functional property is only set on objects such as buttons, knobs, or sliders that want to handle all events, * in conjunction with {@link ActionTool}, pre-empting the normal tool mechanisms. * * The {@link ActionTool} does not conduct any transaction, so if this property has a value, * the function will not be called within a transaction. * If you do provide a function that makes changes to the diagram or to its model, * you should do so within a transaction -- call {@link Diagram.startTransaction} and * {@link Diagram.commitTransaction}. * @see {@link actionDown} * @see {@link actionMove} * @see {@link actionCancel} */ get actionUp(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set actionUp(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * Gets or sets the function to execute when the {@link ActionTool} is cancelled and this GraphObject's {@link isActionable} * is set to true. * This property is infrequently set. * By default this property is null. * * This functional property is only set on objects such as buttons, knobs, or sliders that want to handle all events, * in conjunction with {@link ActionTool}, pre-empting the normal tool mechanisms. * * The {@link ActionTool} does not conduct any transaction, so if this property has a value, * the function will not be called within a transaction. * @see {@link actionDown} * @see {@link actionMove} * @see {@link actionUp} */ get actionCancel(): ((e: InputEvent, thisObj: GraphObject) => void) | null; set actionCancel(value: ((e: InputEvent, thisObj: GraphObject) => void) | null); /** * This {@link Adornment} or {@link HTMLInfo} is shown when the mouse hovers over this object. * The default value is null, which means no tooltip is shown. * * A typical tooltip is defined in the following manner, as taken from * the Kitten Monitor sample: * ```js * myDiagram.nodeTemplate = * new go.Node(..., * { // this tooltip shows the name and picture of the kitten * toolTip: * go.GraphObject.build("ToolTip").add( * new go.Panel("Vertical").add( * new go.Picture() * .bind("source", "src", s => return "images/" + s + ".png"), * new go.TextBlock({ margin: 3 }) * .bind("text", "key") * ) * ) * }).add( * // Node elements ... * ) * ``` * Note that this Adornment depends on having the same data binding as the adorned Part * (i.e. the same value for {@link Panel.data}). * * Tooltips are not copied by {@link copy}, so that tooltips may be shared by all instances of a template. * * Tooltips are shown after a timed delay given by the {@link ToolManager.hoverDelay}. * You can change the delay time by: * ```js * myDiagram = new go.Diagram("myDiagramDiv", * { "toolManager.hoverDelay": 500 }); // 500 milliseconds * ``` * or: * ```js * myDiagram.toolManager.hoverDelay = 500; // 500 milliseconds * ``` * * Tooltips are normally positioned by {@link ToolManager.positionToolTip}. * However, if there is a {@link Placeholder} in the tooltip, the tooltip (i.e. an Adornment) * will be positioned so that the Placeholder is at the same position as this adorned GraphObject. * * Replacing this value will not modify or remove any existing tooltip that is being shown for this object. * * Read more about tooltips at ToolTips. */ get toolTip(): Adornment | HTMLInfo | null; set toolTip(value: Adornment | HTMLInfo | null); /** * This {@link Adornment} or {@link HTMLInfo} is shown upon a context click on this object. * The default value is null, which means no context menu is shown. * * Changing this value will not modify or remove any existing menu that is being shown for this object. * * Context menus may also depend on having the same data binding as the adorned Part * (i.e. the same value for {@link Panel.data}). * * Context menus are not copied by {@link copy}, so that context menus may be shared by all instances of a template. * * A typical context menu is implemented as an Adornment with several buttons in it. * For example, this context menu is defined in the * Dynamic Port sample: * ```js * const nodeMenu = // context menu for each Node * go.GraphObject.build("ContextMenu").add( * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => addPort("top") }) * .add(new go.TextBlock("Add top port")), * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => addPort("left") }) * .add(new go.TextBlock("Add left port")), * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => addPort("right") }) * .add(new go.TextBlock("Add right port")), * go.GraphObject.build("ContextMenuButton", * { click: (e, obj) => addPort("bottom") }) * .add(new go.TextBlock("Add bottom port")) * ); * ``` * and is used in the node template: * ```js * myDiagram.nodeTemplate = * new go.Node("Table", * { . . . * contextMenu: nodeMenu * }).add( * . . . * ); * ``` * * Context menus are normally positioned by {@link ContextMenuTool.positionContextMenu}. * However, if there is a {@link Placeholder} in the context menu, the context menu (i.e. an Adornment) * will be positioned so that the Placeholder is at the same position as this adorned GraphObject. * * The Basic sample also shows how * to make context menu items invisible when the command is disabled. * * Replacing this value will not modify or remove any existing context menu that is being shown for this object. * * Read more about context menus at Context Menus. */ get contextMenu(): Adornment | HTMLInfo | null; set contextMenu(value: Adornment | HTMLInfo | null); /** * Walks up the visual tree and returns the first Panel whose Panel.data is bound to data. * This can be useful when you need to inspect {@link Panel.data} objects. * @since 2.2 */ findBindingPanel(): Panel | null; /** * Add a data-binding to this GraphObject for the given property names and optional conversion functions. * The added Binding will be of kind {@link Binding.isToData}. * * Do not add, modify, or remove any Bindings after this GraphObject has been copied. * * An example using `.bind` with the shorthand arguments: * ```js * myDiagram.nodeTemplate = * new go.Node("Horizontal") * // a OneWay Binding, from data.loc to Node.location * .bind("location", "loc", go.Point.parse) * // ... rest of the Node template * ``` * * To get a TwoWay Binding call {@link Binding.makeTwoWay} instead. * ```js * myDiagram.nodeTemplate = * new go.Node("Horizontal") * // this is now a TwoWay Binding: * .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify) * // ... rest of the Node template * ``` * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * * @param targetprop - A string naming the target property on this GraphObject. * This should not be the empty string. * This becomes the value of {@link Binding.targetProperty}. * @param sourceprop - A string naming the source property on the bound data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * This becomes the value of {@link Binding.sourceProperty}. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * This becomes the value of {@link Binding.converter}. * @param backconv - Deprecated: an optional conversion function to convert GraphObject property values back to data values. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * This becomes the value of {@link Binding.backConverter}. * @returns this GraphObject * @since 2.2 */ bind(targetprop?: string, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion): this; /** * Add a data-binding of a property on this GraphObject to a property on a binding source object. * * Do not add, modify, or remove any Bindings after this GraphObject has been copied. * * An example using `.bind` with the Binding argument: * ```js * myDiagram.nodeTemplate = * new go.Part("Horizontal") * .bind(new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify)) * // ... * ``` * * However, one could achieve the same effect by using a different method: * ```js * myDiagram.nodeTemplate = * new go.Part("Horizontal") * .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify) * // ... * ``` * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param binding * @returns this GraphObject */ bind(binding: Binding): this; /** * This convenience function works like {@link GraphObject.bind}, creating a Binding, then also calls {@link Binding.makeTwoWay} on it. * These are equivalent: * ``` * .bind("text", "text", null, null) * .bindTwoWay("text") * ``` * As are these: * ``` * .bind("text", "someProp", null, null) * .bindTwoWay("text", "someProp") * ``` * * The first creates a two-way binding because specifying anything for the 4th argument (BackConversion) automatically * sets the {@link Binding.mode} to be {@link BindingMode.TwoWay}. However, it requires specifying the middle arguments, which may not be necessary. * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param targetprop - A string naming the target property on this GraphObject. * This should not be the empty string. * This becomes the value of {@link Binding.targetProperty}. * @param sourceprop - A string naming the source property on the bound data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * This becomes the value of {@link Binding.sourceProperty}. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * This becomes the value of {@link Binding.converter}. * @param backconv - An optional conversion function to convert GraphObject property values back to data values. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * This becomes the value of {@link Binding.backConverter}. * @returns this GraphObject * @since 3.0 */ bindTwoWay(targetprop: string | Binding, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion): this; /** * Add a data-binding from the shared {@link Model.modelData} object to a property on this GraphObject. * We recommend that you not use TwoWay binding for this kind of {@link Binding.isToModel} binding. * * This is a convenience function for {@link bind} that additionally calls {@link Binding.ofModel} on the created binding. * See the documentation for {@link bind} for details. * * Note that in order to get a TwoWay Binding one must pass a value for the fourth argument to this method. * Pass null when you do not want a back-conversion function applied when passing a property value from * this target GraphObject to the source data object. * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param targetprop - A string naming the target property on this GraphObject. * This should not be the empty string. * This becomes the value of {@link Binding.targetProperty}. * @param sourceprop - A string naming the source property on the bound shared data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * This becomes the value of {@link Binding.sourceProperty}. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * This becomes the value of {@link Binding.converter}. * @param backconv - An optional conversion function to convert GraphObject property values back to data values. * Note that for TwoWay bindings whenever the target property is modified, the shared data object will be updated. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * This becomes the value of {@link Binding.backConverter}. * @returns this GraphObject * @since 3.0 */ bindModel(targetprop: string | Binding, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion): this; /** * Add a data-binding from a {@link GraphObject} property in this GraphObject's binding Panel to a property on this GraphObject. * We recommend that you use this kind of {@link Binding.isToObject} binding sparingly. * * This is a convenience function for {@link bind} that additionally calls {@link Binding.ofObject} on the created binding. * It passes the param `objectSrcname` to the {@link Binding.ofObject} call. * See the documentation for {@link bind} for details. * * Note that in order to get a TwoWay Binding one must pass a value for the fourth argument to this method. * Pass null when you do not want a back-conversion function applied when passing a property value from * this target GraphObject to the source object. * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param targetprop - A string naming the target property on this target GraphObject. * This should not be the empty string. * This becomes the value of {@link Binding.targetProperty}. * @param sourceprop - A string naming the source property on the source GraphObject. * If this is the empty string, the result of {@link GraphObject.findBindingPanel} is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * This becomes the value of {@link Binding.sourceProperty}. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * This becomes the value of {@link Binding.converter}. * @param backconv - An optional conversion function to convert GraphObject property values back to property values. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * This becomes the value of {@link Binding.backConverter}. * @param objectSrcname - An optional {@link GraphObject.name} used to identify the source GraphObject by calling {@link Panel.findObject}. * If the value is an empty string or is not supplied, the source binding Panel is used -- the Part or the item Panel. * This becomes the value of {@link Binding.sourceName}. * @returns this GraphObject * @since 3.0 */ bindObject(targetprop: string | Binding, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion, objectSrcname?: string): this; /** * Add a {@link ThemeBinding} from a Theme property to a property on this GraphObject. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this GraphObject * @since 3.0 */ theme(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; /** * Add a {@link ThemeBinding} from a data property to a property on this GraphObject. * * This is a convenience function for {@link theme} that additionally calls {@link ThemeBinding.ofData} on the created binding. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this GraphObject * @since 3.0 */ themeData(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; /** * Add a {@link ThemeBinding} from a GraphObject property to a property on this GraphObject. * * This is a convenience function for {@link theme} that additionally calls {@link Binding.ofObject} on the created binding. * It passes the `objectSrcname` param to the {@link Binding.ofObject} call. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @param objectSrcname - the {@link GraphObject.name} of an element in the visual tree of the bound {@link Panel} * If not supplied, it uses the binding Panel as the source GraphObject. * @returns this GraphObject * @since 3.0 */ themeObject(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion, objectSrcname?: string): this; /** * Add a {@link ThemeBinding} from the shared {@link Model.modelData} to a property on this GraphObject. * * This is a convenience function for {@link theme} that additionally calls {@link Binding.ofModel} on the created binding. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this GraphObject * @since 3.0 */ themeModel(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; /** * Set any number of properties on this GraphObject. This is common in initialization. * This method can only be used to set existing properties on this object. To attach new properties, * or to set properties of elements, use {@link GraphObject.setProperties}. * * This method uses TypeScript compile-time type checking, but does no runtime type checking. * If you need to set properties without type checking, or attach new properties, use {@link GraphObject.attach}. * * * ```js * // Common init for use in many different shapes: * const shapeStyle = (() => { return { background: 'red', strokeWidth: 0 }; }) * * // Constructor init is equivalent to "set" * // But if you use common init (eg, shapeStyle()) * // You may wish to set additional properties via "set" * new go.Shape(shapeStyle()) * .bind("fill", "color") * .bind("strokeWidth", "width") * .set({ // more init via set * figure: "RoundedRectangle" * }) * ``` * * @since 2.2 * @param config * @returns this GraphObject * @see {@link setProperties} */ set(config: Partial): this; /** * This method sets a collection of properties according to the property/value pairs on the given Object, or array of Objects, * in the same manner as {@link GraphObject.make} does when constructing a GraphObject. * * This method is used in initialization, but typically you should use {@link set} instead, * unless you need to attach new properties that do not exist on the GraphObject, or to set sub-properties. * Calling this method is much less efficient than setting properties directly, and does not do compile-time type checking. * * ```js * new go.Shape() * .bind("fill", "color") * .bind("strokeWidth", "width") * .attach({ // use .attach for untyped property attachments * "_color": "Red" * }) * ``` * * @since 2.2 * @param config - a JavaScript object containing properties to attach, or an array of such objects. * @returns this GraphObject * @see {@link setProperties} a synonym of this method * @see {@link set} a type-safe method to set a collection of properties */ attach(config: any): this; /** * This method takes a function that can be used to apply multiple settings, bindings, * or {@link Panel.add} calls, to different GraphObjects. This is common in initialization. * If you are just adding settings, bindings, or GraphObjects to a single GraphObject, * you do not need to use this, you can just chain calls to {@link set}, {@link bind}, * and {@link Panel.add} instead. This method is mostly useful when setting the same values * across multiple GraphObjects. * * For example: * * ```js * // This can be used by several node templates * // to set multiple properties and bindings on each * function nodeStyle(node) { * node * .set({ background: 'red' }) * .bind("location") * .bind("desiredSize", "size", go.Size.parse) * } * * // ... in a Node template: * new go.Node("Auto") * .apply(nodeStyle) * .add( * new go.Shape( ... ), * new go.Panel( ... ) * ) * // ...rest of Node template * * // ... in another Node template: * new go.Node("Vertical", { padding: 5 }) * .apply(nodeStyle) * // ...rest of Node template * ``` * * @since 2.2 * @param func - a function that takes this GraphObject * @returns this GraphObject * @see {@link set} a type-safe method to set a collection of properties */ apply(func: ((thisObject: this) => void)): this; /** * This method sets a collection of properties according to the property/value pairs on the given Object, * in the same manner as {@link GraphObject.make} does when constructing a GraphObject with an argument that is a simple JavaScript Object. * * This method is common in initialization, but typically you should use {@link set} instead, * unless you need to attach new properties, or set sub-properties. * Calling this method is much less efficient than setting properties directly, and does not do compile-time type checking. * * If this is a {@link Panel}, you can set properties on named elements within the panel by using a *name.property* syntax for the property name. * For example, if a {@link Node} has a {@link Picture} that is named "ICON" (because its {@link name} property has been set to "ICON") * and a {@link TextBlock} whose name is "TB", one could set properties on the Node and on each of those named elements by: * ```js * aNode.setProperties({ * background: "red", * "ICON.source": "https://www.example.com/images/alert.jpg", * "TB.font": "bold 12pt sans-serif" * }); * ``` * * At the current time only a single dot is permitted in the property "name". * Note that the use of all-upper-case object names is simply a convention. * * @param props - a plain JavaScript object with various property values to be set on this GraphObject. * @returns this GraphObject * @see {@link attach} a synonym of this method * @see {@link set} a type-safe method to set a collection of properties */ setProperties(props: ObjectData): this; /** * This static function builds an object given its class and additional arguments * providing initial properties or {@link GraphObject}s that become {@link Panel} elements. * * The first argument must be the class type or the name of a class or the name of a predefined kind of Panel. * This function will construct a new instance of that type and use the rest of the arguments to initialize the object. * The first argument cannot be a regular Object (such as a GraphObject) that you are trying to initialize; * for that you can call {@link setProperties} or {@link Diagram.setProperties}, although that would * be less efficient than setting properties directly. * * If an initializer argument is an enumerated value, this tries to set the property that seems most appropriate. * * If an initializer argument is a string, this sets a particular property depending on the type of object being built. * - If the object is a {@link TextBlock}, it sets {@link TextBlock.text}. * - If the object is a {@link Shape}, it sets {@link Shape.figure}. * - If the object is a {@link Picture}, it sets {@link Picture.source}. * - If the object is a {@link Panel} (including {@link Part}, {@link Node}, or {@link Group}), it sets {@link Panel.type}. * * If an initializer argument is a particular kind of object, this can add that object to the object being built. * - {@link GraphObject}s and {@link RowColumnDefinition}s can only be added as elements of {@link Panel}s. * - {@link Binding}s can only be applied to {@link GraphObject}s and {@link RowColumnDefinition}s. * - {@link PathFigure}s can only be added to {@link Geometry} objects. * - {@link PathSegment}s can only be added to {@link PathFigure} objects. * - Regular JavaScript Arrays provide a sequence of initializer arguments. * - Regular JavaScript objects provide property/value pairs that are set on the object being built. * * When the initializer argument is a plain JavaScript Object, there are several ways that that object's properties are applied. * If the property name is a string with a period inside it, this has a special meaning if the object is a {@link Panel} or a {@link Diagram}. * At the current time only a single period separator is valid syntax for a property string, and it is valid only on Panels and Diagrams. * * For Panels, the substring before the period is used as the name passed to {@link Panel.findObject} * to get the actual object on which to set the property, which is the substring after the period. * This is normally useful only on the predefined Panels: * - a **"Button"** has a {@link Shape} named "ButtonBorder" surrounding the content of the Panel. * - a **"TreeExpanderButton"** has a "ButtonBorder" Shape and a "ButtonIcon" Shape that is the plus-or-minus sign. * - a **"SubGraphExpanderButton"** has a "ButtonBorder" Shape and a "ButtonIcon" Shape that is the plus-or-minus sign. * - a **"ContextMenuButton"** has a Shape named "ButtonBorder" surrounding the content of the Panel. * * But you can define your own names that GraphObject.make can build by calling the static function {@link GraphObject.defineBuilder}. * * For Diagrams, the substring before the period is used as the name of a property on the Diagram itself * to get the actual object on which to set the property. * As a special case, if such a property value does not exist on the Diagram, it looks on the {@link Diagram.toolManager}. * See some examples below. * * Also for Diagrams, and only for Diagrams, if the property name is the name of a {@link DiagramEvent}, * the property value must be a DiagramEvent listener function, and {@link Diagram.addDiagramListener} is called * using that DiagramEvent name and that function. * Note that all DiagramEvent names are capitalized and do not contain any periods, * so there cannot be any name conflicts with any properties on {@link Diagram} or {@link ToolManager}. * Although you can register multiple listeners for the same DiagramEvent names, due to JavaScript limitations * those need to be declared using separate JavaScript objects, because JavaScript does not permit duplicate property names * in an Object literal. * * Furthermore for Diagrams, if the property name is `"Changed"` or `"ModelChanged"`, * the property value must be a ChangedEvent listener function, which is called with a {@link ChangedEvent} argument. * When the property name is `"Changed"`, it calls {@link Diagram.addChangedListener}, * notifying about changes to the Diagram or its Layers or GraphObjects. * When the property name is `"ModelChanged"`, it calls {@link Model.addChangedListener} on the {@link Diagram.model}, * resulting in notifications about changes to the Model or its data. * This is handy because the {@link Diagram.model} property setter will automatically call * {@link Model.removeChangedListener} on the old model, thereby avoiding any overhead if there are any * more changes to the old model and also avoiding a reference to the listener which might cause garbage collection retention. * It also will call {@link Model.addChangedListener} on the new model, helping implement the same behavior with the new model. * * If the property name is a number and if the object being constructed is a {@link Brush}, * the number and value are added to the Brush by calling {@link Brush.addColorStop}. * * Otherwise the property name is used as a regular property name on the object being built. * This tries to do some property name and value checking: * when a property is not defined on the object being built, it will signal an error. * Many typos can be found this way that would be ignored by JavaScript code. * * If the property name begins with an underscore, this will not complain about the property being undefined. * Not only is that underscore property set on the object being built, but calls to {@link copy} * will also copy the values of such named properties to the new objects. * ```js * const diagram = * new go.Diagram("myDiagramDiv", * { * // don't initialize some properties until after a new model has been loaded * "InitialLayoutCompleted": loadDiagramProperties, * allowZoom: false, // don't allow the user to change the diagram's scale * "grid.visible": true, // display a background grid for the whole diagram * "grid.gridCellSize": new go.Size(20, 20), * // allow double-click in background to create a new node * "clickCreatingTool.archetypeNodeData": { text: "Node" }, * // allow Ctrl-G to call the groupSelection command * "commandHandler.archetypeGroupData": * { text: "Group", isGroup: true, color: "blue" }, * "toolManager.hoverDelay": 100, // how quickly tooltips are shown * // mouse wheel zooms instead of scrolls * "toolManager.mouseWheelBehavior": go.WheelMode.Zoom, * "commandHandler.copiesTree": true, // for the copy command * "commandHandler.deletesTree": true, // for the delete command * "draggingTool.dragsTree": true, // dragging for both move and copy * "draggingTool.isGridSnapEnabled": true, * layout: new go.TreeLayout( * { angle: 90, sorting: go.TreeLayout.SortingAscending }) * }); * * diagram.nodeTemplate = * new go.Node("Auto") // or go.Panel.Auto * .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify).add( * new go.Shape("RoundedRectangle", * { * fill: new go.Brush("Linear", { 0: "#FEC901", 1: "#FEA200" }), * stroke: "gray", * strokeWidth: 2, * strokeDashArray: [3, 3] * }), * new go.TextBlock( * { margin: 5, font: "bold 12pt sans-serif" }) * .bind("text", "key") * ); * ``` *

* See the Introduction page on building objects * for usage information and examples of GraphObject.make. * @param cls - a class function or the name of a class in the `go` namespace, * or one of several predefined kinds of {@link Panel}s: `"Button"`, `"TreeExpanderButton"`, * `"SubGraphExpanderButton"`, or `"ContextMenuButton"`. * @param initializers - zero or more values that initialize the new object, * typically an Object with properties whose values are set on the new object, * or a JavaScript Array with additional initializer arguments, * or a {@link GraphObject} that is added to a {@link Panel}, * or a {@link Binding} for one of the new object's properties, * or a constant value as the initial value of a single property of the new object that * is recognized to take that value, * or a string that is used as the value of a commonly set property. */ static make(// for specific named builders cls: ('ToolTip' | 'ContextMenu'), ...initializers: Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout | Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout>>): T; static make(// for specific named Panel builders cls: ('Button' | 'TreeExpanderButton' | 'SubGraphExpanderButton' | 'ContextMenuButton' | 'PanelExpanderButton' | 'CheckBoxButton' | 'CheckBox'), ...initializers: Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout | Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout>>): T; static make(cls: string, // for named Panel builders ...initializers: Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout | Array & { [p: string]: any; }) | Binding | AnimationTrigger | number | RowColumnDefinition | PanelLayout>>): T; static make>(cls: CT, ...initializers: Array> & { [p: string]: any; } & (InstanceType extends Diagram ? DiagramEventsInterface & { Changed?: ChangedEventHandler; ModelChanged?: ChangedEventHandler; } : unknown)) | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | number | HTMLDivElement | Array> & { [p: string]: any; } & (InstanceType extends Diagram ? DiagramEventsInterface & { Changed?: ChangedEventHandler; ModelChanged?: ChangedEventHandler; } : unknown)) | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | MakeAllow | number>>): InstanceType; /** * This static function creates an instance that was defined with {@link GraphObject.defineBuilder}. * Once this is called one can use the name as the first argument for {@link GraphObject.make}. * Names are case sensitive. * * The second is an optional settings configuration object, equivalent to calling {@link GraphObject.set} * on the new object. * * Predefined builder names include: `"Button"`, `"TreeExpanderButton"`, `"SubGraphExpanderButton"`, * `"PanelExpanderButton"`, and `"ContextMenuButton"`. * The implementation of these builders is provided by Buttons.js * in the Extensions directory. * * @param name - a capitalized name; must not be `""` or `"None"` * @param config - a plain JavaScript object with various property values to be set on this GraphObject. * @param args - If defined in the builder, the additional arguments that would be passed to {@link GraphObject.takeBuilderArgument} * @since 2.2 */ static build(name: ('ToolTip' | 'ContextMenu'), config?: Partial & ObjectData, ...args: Array): T; static build(name: ('Button' | 'TreeExpanderButton' | 'SubGraphExpanderButton' | 'ContextMenuButton' | 'PanelExpanderButton' | 'CheckBoxButton' | 'CheckBox'), config?: Partial & ObjectData, ...args: Array): T; static build(name: string, config?: Partial & ObjectData, ...args: Array): T; /** * This static function defines a named function that {@link GraphObject.make} or {@link GraphObject.build} can use to build objects. * Once this is called one can use the name as the first argument for {@link GraphObject.make} or {@link GraphObject.build}. * Names are case sensitive. * * The second argument must be a function that returns a newly created object, typically a {@link GraphObject}. * It is commonplace for that object to be a {@link Panel} holding a newly created visual tree of GraphObjects. * The function receives as its only argument an Array that is holds all of the arguments that are being * passed to {@link GraphObject.make}, which it may modify in order to change the arguments that GraphObject.make receives. * * Predefined builder names include: `"Button"`, `"TreeExpanderButton"`, `"SubGraphExpanderButton"`, * `"PanelExpanderButton"`, and `"ContextMenuButton"`. * The implementation of these builders is provided by Buttons.js * in the Extensions directory. * @param name - a capitalized name; must not be `""` or `"None"` * @param func - that takes an Array of `GraphObject.make` arguments and returns a new object */ static defineBuilder(name: string, func: ((a: Array) => ObjectData)): void; /** * This static predicate is true if and only if {@link GraphObject.defineBuilder} has been called on the given name. * @param name */ static isBuilderDefined(name: string): boolean; /** * This static function returns the first argument from the arguments array passed * to a {@link GraphObject.defineBuilder} function by {@link GraphObject.make}. * By default this requires the first argument to be a string, * but you can provide a predicate to determine whether the argument is suitable. * @param args - the arguments Array passed to the builder function; * this may be modified if an acceptable argument is found and returned * @param defval - the default value to return if the argument is optional and not present as the first argument; * otherwise throw an error when the argument is not there * @param pred - a predicate to determine the acceptability of the argument; * the default predicate checks whether the argument is a string */ static takeBuilderArgument(args: Array, defval?: any, pred?: ((a: any) => boolean) | null): any; } /** */ export class SGradient { /** * @param aType */ constructor(aType: string); } /** * This enumeration specifies possible values for {@link Brush.type}. * @since 3.0 * @category Geometry */ export declare enum BrushType { /** * For simple, solid color brushes. */ Solid = 1, /** * For linear gradient brushes. */ Linear = 2, /** * For radial gradient brushes. */ Radial = 3, /** * For pattern brushes. */ Pattern = 4 } /** * This enumeration specifies possible values used for lightening and darkening. * @see {@link Brush.lightenBy} * @see {@link Brush.darkenBy} * @since 3.0 * @category Geometry */ export declare enum ColorSpace { /** * The Lab (CIELAB) color space. More closely matches human perception of lightness. */ Lab = 1, /** * The HSL (hue, saturation, lightness) color space. */ HSL = 2, /** * A newer color space, tending to be more accurate than Lab for this lightening and darkening, * as seen in Section 13.1.6 in https://www.w3.org/TR/css-color-4/#lch-to-lab * @since 3.0 */ Oklch = 3 } /** * The BrushLike type is the same as `Brush | string | null`. * A string in place of a Brush object is treated as a Solid Brush of that color. */ export type BrushLike = Brush | string | null; /** * A Brush holds color information and describes how to draw the inside * of a {@link Shape} or the stroke of a shape or a {@link TextBlock} or the * background of any {@link GraphObject}. * * A Brush must not be modified once it has been assigned to a {@link GraphObject}, * such as the {@link Shape.fill} or {@link TextBlock.stroke} * or {@link GraphObject.background}. * However, a Brush may be shared by multiple GraphObjects. * @category Geometry */ export class Brush { /** * Construct a Brush class that holds the given color information. * @param type - Optional, one of the values {@link BrushType.Solid}, {@link BrushType.Linear}, {@link BrushType.Radial}, {@link BrushType.Pattern}, * or a well-formed CSS string describing a solid color brush. No parameter * defaults to a {@link BrushType.Solid} with a color description of 'black'. * @param init - Optional initialization properties. * In addition to Brush properties, this object can also contain color stops in the format: * `{ 0: "#FEC901", 0.2: "#FFFFAA", 1: "#FEA200" }` */ constructor(type?: BrushType | string, init?: Partial & Record); /** * Create a copy of this Brush with the same values. */ copy(): Brush; /** * Specify a particular color at a particular fraction of the distance. * If the {@link type} is {@link BrushType.Solid}, change the type to {@link BrushType.Linear}. * You should not have duplicate color stop values at the same fractional distance. * @param loc - A number between 0 and 1 (inclusive). * @param color - A valid CSS color string. * @returns this Brush */ addColorStop(loc: number, color: string): this; /** * Gets or sets the type of brush. * The default value is {@link BrushType.Solid}. * The value must be a {@link BrushType}. * If the new value is a linear or radial brush type, * and if the {@link start} or {@link end} spots are not specific spots, * they are changed to be specific spots, depending on the type of brush. */ get type(): BrushType; set type(value: BrushType); /** * Gets or sets the color of a solid Brush. * The default value is 'black'. * The value must be a valid CSS color string. */ get color(): string; set color(value: string); /** * Gets or sets the starting location for a linear or radial gradient. * A {@link Spot} value specifies a relative point in the object's {@link GraphObject.naturalBounds}. * The default value is {@link Spot.TopCenter} for linear gradients and {@link Spot.Center} for radial gradients. */ get start(): Spot; set start(value: Spot); /** * Gets or sets the ending location for a linear or radial gradient. * A {@link Spot} value specifies a relative point in the object's {@link GraphObject.naturalBounds}. * The default value is {@link Spot.BottomCenter} for linear gradients and {@link Spot.Center} for radial gradients. */ get end(): Spot; set end(value: Spot); /** * Gets or sets the radius of a radial brush at the start location. * The default value is 0. */ get startRadius(): number; set startRadius(value: number); /** * Gets or sets the radius of a radial brush at the end location. * The default value is NaN. */ get endRadius(): number; set endRadius(value: number); /** * Gets or sets a Map holding all of the color stops used in this gradient, * where the key is a number, the fractional distance between 0 and 1 (inclusive), * and where the corresponding value is a color string. * * Call {@link addColorStop} in order to add color stops to this brush. * This property value may be null if no gradient stops have been defined. */ get colorStops(): Map | null; set colorStops(value: Map | null); /** * Gets or sets the pattern of a brush of type {@link BrushType.Pattern}. */ get pattern(): HTMLCanvasElement | HTMLImageElement | null; set pattern(value: HTMLCanvasElement | HTMLImageElement | null); /** * This static function can be used to generate a random color. * @param min - A number between 0 and 255, defaults to 128. * @param max - A number between 0 and 255, defaults to 255. * @returns A color value in # hexadecimal format. */ static randomColor(min?: number, max?: number): string; /** * This static function returns true if a given color string is well-formed for drawing. * @param color - A color string to validate. */ static isValidColor(color: string): boolean; /** * This static function takes a color and lightens it by 20% in the Lab color space. * This is a convenience function which calls {@link Brush.lightenBy}. * @param color - A valid CSS color string. * @returns A CSS string for the lightened color in RGBA. */ static lighten(color: string): string; /** * Modifies all colors within this Brush, lightening them by some fraction. * @param fraction - Fraction to lighten the colors by. Defaults to 0.2, must be between 0 and 1 (inclusive). * @param mode - Color space to use for adjusting. Must be a {@link ColorSpace} value, defaults to {@link ColorSpace.Oklch}. * @returns This Brush with modified color values. */ lightenBy(fraction?: number, mode?: ColorSpace): this; /** * This static function takes a color and lightens it. * @param color - A valid CSS color string. * @param fraction - Fraction to lighten the colors by. Defaults to 0.2, must be between 0 and 1 (inclusive). * @param {ColorSpace=} mode Color space to use for adjusting. Must be a {@link ColorSpace} value, defaults to {@link ColorSpace.Oklch}. * @returns A CSS string for the lightened color in RGBA or HSLA. */ static lightenBy(color: string, fraction?: number, mode?: ColorSpace): string; /** * This static function takes a color and darkens it by 20% in the Lab color space. * This is a convenience function which calls {@link Brush.darkenBy}. * @param color - A valid CSS color string. * @returns A CSS string for the darkened color in RGBA. */ static darken(color: string): string; /** * Modifies all colors within this Brush, darkening them by some fraction. * @param fraction - Fraction to darken the colors by. Defaults to 0.2, must be between 0 and 1 (inclusive). * @param mode - Color space to use for adjusting. Must be a {@link ColorSpace} value, defaults to {@link ColorSpace.Oklch}. * @returns This Brush with modified color values. */ darkenBy(fraction?: number, mode?: ColorSpace): this; /** * This static function takes a color and darkens it. * @param color - A valid CSS color string * @param fraction - Fraction to darken the color by. Defaults to 0.2, must be between 0 and 1 (inclusive). * @param mode - Color space to use for adjusting. Must be a {@link ColorSpace} value, defaults to {@link ColorSpace.Oklch}. * @returns A CSS string for the darkened color in RGBA or HSLA. */ static darkenBy(color: string, fraction?: number, mode?: ColorSpace): string; /** * This static function takes two colors and mixes them together, using the (optionally) specified amount of the second color. * @param color1 - A valid CSS color string. * @param color2 - Another valid CSS color string to mix. * @param fraction - Fraction specifying how much color2 to mix into color1. Defaults to .5, must be between 0 and 1 (inclusive). * @since 2.0 */ static mix(color1: string, color2: string, fraction?: number): string; /** * This function determines whether this Brush is "dark." * @since 2.0 */ isDark(): boolean; /** * This static function takes a color and determines whether it is "dark." Does not account for transparency. * * Example usage: * ```js * myDiagram.nodeTemplate = * new go.Node('Auto') * .add( * new go.Shape('RoundedRectangle', { strokeWidth: 0 }) * .bind('fill', 'color'), * new go.TextBlock({ margin: 8 }) * // Dark nodes use white text, light nodes use black text * .bind('stroke', 'color', c => go.Brush.isDark(c) ? 'white' : 'black') * .bind('text', 'key') * ); * ``` * @param color - A valid CSS color string or a Brush. * @since 2.0 */ static isDark(color: BrushLike): boolean; /** * @deprecated See {@link BrushType.Solid}. */ static readonly Solid = BrushType.Solid; /** * @deprecated See {@link BrushType.Linear}. */ static readonly Linear = BrushType.Linear; /** * @deprecated See {@link BrushType.Radial}. */ static readonly Radial = BrushType.Radial; /** * @deprecated See {@link BrushType.Pattern}. */ static readonly Pattern = BrushType.Pattern; /** * @deprecated See {@link ColorSpace.Lab}. */ static readonly Lab = ColorSpace.Lab; /** * @deprecated See {@link ColorSpace.HSL}. */ static readonly HSL = ColorSpace.HSL; } /** * This is the abstract base class for all Panel Layouts, which inform the possible Panel types. * It is possible to create your own Panel type by creating a subclass of PanelLayout, * though this is not common and not recommended for beginners. * * By default, GoJS has 12 Panel types, each corresponding to a PanelLayout subclass: * - 'Position', `PanelLayoutPosition` * - 'Horizontal', `PanelLayoutHorizontal` * - 'Vertical', `PanelLayoutVertical` * - 'Spot', `PanelLayoutSpot` * - 'Auto', `PanelLayoutAuto` * - 'Table', `PanelLayoutTable` * - 'Viewbox', `PanelLayoutViewbox` * - 'TableRow', `PanelLayoutTableRow` * - 'TableColumn', `PanelLayoutTableColumn` * - 'Link', `PanelLayoutLink` * - 'Grid', `PanelLayoutGrid` * - 'Graduated', `PanelLayoutGraduated` * * None of these predefined panel layout classes have their own documentation pages. * * These panel layouts are included by default in builds of `go.js` and `go-module.js` and their respective debug versions. * When building from source, you can optionally exclude all of them except `Position`, * `Vertical`, `Auto`, `Link`, and `Grid`. * * Registering a new PanelLayout is done by calling the static function, {@link Panel.definePanelLayout}: * * ```js * PanelLayout.definePanelLayout('Custom', new PanelLayoutCustom()); * ``` * * Each PanelLayout must define a {@link measure} and {@link arrange} method. * The measure method must call {@link measureElement} with each element of the Panel, * which sets each element's {@link GraphObject.measuredBounds}. These bounds can be used to determine object layout. * The arrange method must call {@link arrangeElement} with each element of the Panel to position the objects relative to the Panel. * Remember that each Panel defines its own coordinate system, which is used for sizing and positioning of the panel's elements. * * An instance of a PanelLayout is shared by all copies of a Panel that uses it. * * There is an example PanelLayout in the PanelLayout sample. * There is a Flow PanelLayout extension at {@link PanelLayoutFlow}, demonstrated at * Flow PanelLayout sample. * @since 2.0 */ export abstract class PanelLayout { /** * Gets or sets the name of this instance of a particular panel layout. */ get name(): string; set name(value: string); /** * This class is abstract. Define your own subclass if you want to implement a custom panel layout. */ constructor(); /** * (undocumented) */ get classType(): Function; /** * Given the available size, measure the Panel and * determine its expected drawing size. * * This must call {@link measureElement} with each Panel element, which will set the * {@link GraphObject.measuredBounds} of those elements. Depending on how the Panel intends to lay out its elements, * the programmer must construction the `union` by setting `union.width` and `union.height` of the supplied argument. * For example PanelLayoutHorizontal measures its elements and sums their widths to set its `union.width`, * and takes the maximum of their heights to set its `union.height`. * * This union must reflect the measured size of the Panel. After measure is called, the Panel class will modify this union Rect, * constraining its size by the Panel's {@link GraphObject.desiredSize}, {@link GraphObject.minSize}, and {@link GraphObject.maxSize}, * before passing it to {@link arrange}. * * @virtual * @param panel - Panel which called this layout * @param width - expected width of the Panel, informed by any containing Panel and by the Panel's own * {@link GraphObject.desiredSize}, {@link GraphObject.minSize}, and {@link GraphObject.maxSize}. * Often Infinity. * @param height - expected height of the Panel. * @param elements - Array of Panel elements * @param union - rectangle to be modified to contain the expected union bounds of every element in the Panel, * to be potentially used in {@link arrange}. * @param minw - expected minimum width of the Panel, informed by any containing Panel. Often zero. * @param minh - expected minimum height of the Panel. */ measure(panel: Panel, width: number, height: number, elements: Array, union: Rect, minw: number, minh: number): void; /** * Given the available size, measure one element of the Panel and * determine its expected drawing size. This sets the {@link GraphObject.measuredBounds} of the object, * which can then be used to determine the arrangement of objects in the PanelLayout. * * @param obj - Panel which called this layout * @param width - expected width of the GraphObject * @param height - expected height of the GraphObject * @param minw - minimum width of the GraphObject * @param minh - minimum height of the GraphObject */ protected measureElement(obj: GraphObject, width: number, height: number, minw: number, minh: number): void; /** * After measuring, a Panel must arrange each element, giving the elements a position and size in the Panel's coordinate system. * This must call {@link arrangeElement} with each Panel element, which will set that element's {@link GraphObject.actualBounds}. * * For arranging some elements, it is useful to know the total unioned area of every element, which is given as the `union` argument. * This Rect can be used to right-align or center-align, etc, elements within an area. * * For example, PanelLayoutHorizontal arranges each element sequentially, starting with an `x` value of `0`, * and increasing it by each previous element's {@link GraphObject.measuredBounds} `width`. * The horizontal Panel arranges each element with a `y` value determined by the `union` argument's `height` * considering the {@link GraphObject.alignment} of the element, and the GraphObject's own `measuredBounds.height`. * * * @virtual * @param panel - Panel which called this layout * @param elements - Array of Panel elements * @param union - rectangle, if properly constructed in {@link measure}, that contains the expected union bounds of every element in the Panel. */ arrange(panel: Panel, elements: Array, union: Rect): void; /** * Arranges the GraphObject onto its parent Panel. * The passed-in numbers typically account for {@link GraphObject.margin} and other offsets. * The `x` and `y` coordinates are where GraphObjects will be placed within the Panel's own coordinates * (from the Panel's top-left corner). The `width` and `height` are the size it will take up within the Panel's coordinates. * * This sets the {@link GraphObject.actualBounds} of the `obj`. * * @param obj - GraphObject to be arranged. * @param x - The final x value of actualBounds that the Panel computes for the GraphObject. * @param y - The final y value of actualBounds that the Panel computes for the GraphObject. * @param width - The final width value of actualBounds that the Panel computes for the GraphObject. * @param height - The final height value of actualBounds that the Panel computes for the GraphObject. * @param clipRect - an optional area to constrain this actualBounds to when picking and drawing. * By default, this is only used with Table Panel elements, which are clipped to their cell sizes. */ protected arrangeElement(obj: GraphObject, x: number, y: number, width: number, height: number, clipRect?: Rect): void; /** * Uncommon: Force a given GraphObject to remeasure in the near future. * If a PanelLayout is not just measuring elements, but must also modify some of its elements, * this must be called on those elements before modifications are made. * This prevents the elements from potentially remeasuring * the entire visual tree, which would cause an infinite loop. * * Normally, panels do not modify the dimensions of their elements. In other words, a Panel * would not normally set a property like {@link GraphObject.desiredSize} or {@link TextBlock.text} * or {@link Shape.geometry} on any of its elements. Some custom panels may wish to do this, * especially if the programmer knows it will not affect the size of any containing Panel. * * Calling this method before changing a property preempts the remeasuring of any containing Panels, * ensuring only the GraphObject and its own child elements will be remeasured. * * This is used in {@link PanelLayout} "Viewbox" on its one element. * It modifies that element's {@link GraphObject.scale} and is certain that will not * affect Panels up the visual tree. * @since 2.2 * @param obj - GraphObject to be invalidated. */ remeasureObject(obj: GraphObject): void; } /** * This enumeration specifies possible values for {@link Panel.viewboxStretch}. * @since 3.0 */ export declare enum ViewboxStretch { /** * Scale the contained element equally in both directions to fit the larger side of the element's bounds in the given bounds. */ Uniform = 6, /** * Scale the contained element equally in both directions to fit the smaller side of the element's bounds in the given bounds. * There may be clipping in on dimension. */ UniformToFill = 7 } /** * A Panel is a {@link GraphObject} that holds other GraphObjects as its elements. * A Panel is responsible for sizing and positioning its elements. * The elements of a panel are drawn in the order in which they appear in the {@link elements} collection. * * The {@link Part} class inherits from Panel; Part in turn is the base class of {@link Node} and {@link Link}. * * Every Panel has a {@link type} and establishes its own coordinate system. The type of a Panel * determines how it will size and arrange its elements: * - {@link Panel.Position} is used to arrange elements based on their absolute positions within the Panel's local coordinate system. * - {@link Panel.Vertical} and {@link Panel.Horizontal} are used to create linear "stacks" of elements. * - {@link Panel.Auto} is used to size the main element to fit around other elements in the Panel -- this creates borders. * - {@link Panel.Spot} is used to arrange elements based on the {@link Spot} properties {@link GraphObject.alignment} * and {@link GraphObject.alignmentFocus}, relative to a main element of the panel. * Spot panels can align relative to other elements by using {@link Panel.alignmentFocusName}. * - {@link Panel.Table} is used to arrange elements into rows and columns, typically employing the different * elements' {@link GraphObject.row}, {@link GraphObject.rowSpan}, {@link GraphObject.column}, * and {@link GraphObject.columnSpan} properties. This Panel type also makes use of {@link RowColumnDefinition}. * - {@link Panel.TableRow} and {@link Panel.TableColumn} can only be used immediately within a {@link Panel.Table} Panel * to organize a collection of elements as a row or as a column in a table. * - {@link Panel.Viewbox} is used to automatically resize a single element to fit inside the panel's available area. * - {@link Panel.Grid} is not used to house typical elements, but is used only to draw regular patterns of lines. * The elements must be {@link Shape}s used to describe the repeating lines. * - {@link Panel.Link} is only used by {@link Link} parts and Link Adornments. * - {@link Panel.Graduated} is used to draw regular tick marks and text along the main {@link Shape} element. * * The first argument to the constructor can be used to declare the Panel type. * ```js * // Either: * new go.Panel(go.Panel.Horizontal, ... * // Or: * new go.Panel("Horizontal", ... * * // Full example: * p = new go.Panel("Horizontal", * { width: 60, height: 60 }) // panel properties * // elements in the panel: * .add( * new go.Shape("Rectangle", { stroke: "lime" }), * new go.TextBlock("Some Text") * ); * ``` * The first argument may also be an instance of {@link PanelLayout}, if you want to use a custom panel layout. * *

* For an overview of most Panel types, please read the Introduction page on Panels. * * {@link Panel.Vertical} and {@link Panel.Horizontal} panels are frequently used to position two or more GraphObjects * vertically above each other or horizontally next to each other. Use the {@link GraphObject.alignment} or * {@link GraphObject.stretch} properties on the individual elements to control their position and size. * Set {@link isOpposite} to true if you want the elements arranged from right-to-left in Horizontal Panels * or from bottom-to-top in Vertical Panels. * * {@link Panel.Spot} and {@link Panel.Auto} panels have a "main" element, signified by the Panel's first element * with {@link GraphObject.isPanelMain} set to true. If there is no such element, it uses the first element as the "main" one. * Use the {@link GraphObject.alignment} property to position elements with respect to the main element. * Use the {@link GraphObject.alignmentFocus} property to further specify the position within Spot Panels. * "Spot" and "Auto" Panels should have two or more elements in them. * * In {@link Panel.Table} panels you will want to set the {@link GraphObject.row} and {@link GraphObject.column} * properties on each element. The {@link GraphObject.alignment} and {@link GraphObject.stretch} properties are also * useful when an element's table cell is larger than that element. *

Please read the Introduction page on Table Panels * for more examples and explanation. * * {@link Panel.TableRow} and {@link Panel.TableColumn} panels can only be used as elements within a {@link Panel.Table} Panel. * They are typically only used in item templates, e.g. for automatically creating rows in a Table Panel based on model data * provided in an {@link itemArray}. You will still need to specify properties on the individual elements within a TableRow * or TableColumn as if they were immediate elements of the containing Table panel. *

For an example that uses TableRow Panels, see Records sample. * * {@link Panel.Grid} panels are often used for the Diagram's {@link Diagram.grid}. * ```js * const diagram = new go.Diagram("myDiagramDiv", * // Diagram options: * { . . . * grid: new go.Panel("Grid", * { gridCellSize: new go.Size(40, 40) }) * .add( * new go.Shape("LineH", { stroke: "lightgray" }), * new go.Shape("LineV", { stroke: "lightgray" }) * ), * . . . * }); * ``` * Or to get a green bar effect: * ```js * const diagram = new go.Diagram("myDiagramDiv", * { . . . * grid: new go.Panel("Grid", * { gridCellSize: new go.Size(100, 100) }) * .add(new go.Shape("BarH", { fill: "lightgreen", height: 50 })), * . . . * }); * ``` * But Grid Panels can also be stand alone objects: * ```js * new go.Node("Grid", * { gridCellSize: new go.Size(6, 6), width: 60, height: 60 }) * .add( * new go.Shape("LineH", { stroke: "gray" }), * new go.Shape("LineV", { stroke: "gray" }) * ) * ``` * * A Grid Panel's elements do not participate in object picking. *

Please read the Introduction page on Grid Patterns * for more examples and explanation. * * {@link Panel.Graduated} panels, like Spot and Auto Panels have a "main" element. The other elements within a Graduated Panel * are used to define ticks and labels to draw along the main shape's path. * ```js * new go.Part("Graduated") * .add( * new go.Shape({ geometryString: "M0 0 H400" }), * new go.Shape({ geometryString: "M0 0 V10" }), * // offset to display below ticks * new go.TextBlock({ segmentOffset: new go.Point(0, 12) }) * ) * ``` * * Only the main shape of a Graduated Panel participates in object picking, but a `background` * can be set if the entire panel needs to be pickable. * You cannot set or bind the {@link Panel.itemArray} of a Graduated Panel. * Events on the tick Shapes and TextBlock labels of a Graduated Panel will be ignored. * Graduated Panel TextBlock labels cannot be edited. * * Rotating the main shape will not rotate the ticks, just as rotating a Spot Panel's main element * won't rotate its children. Rotation should generally be done at the Panel level. Another similarity * to Spot Panels is that resizing of a Graduated Panel should generally be done on the main shape. *

Please read the Introduction page on Graduated Panels * for more examples and explanation. * *

Changing and accessing elements of a Panel

* * You can change the collection of {@link elements} by calling {@link add}, {@link insertAt}, {@link remove}, or {@link removeAt}. * You can get direct access to a particular element by calling {@link elt}. * * Alternatively you can control the number and order of elements that are copies of an item template by setting or binding the * {@link itemArray} property. This is discussed below. * * You can search the visual tree of a Panel for GraphObjects that given a {@link GraphObject.name} using {@link findObject}. * *

Panel Size and Appearance

* * Panels typically compute their own size based on their elements and Panel {@link type}, * but can also be sized by setting {@link GraphObject.desiredSize}, {@link GraphObject.minSize}, and {@link GraphObject.maxSize}. * Setting an explicit size on a Panel may cause nested elements of that panel to size themselves differently, * especially in the cases of nested elements having a {@link GraphObject.stretch} value or {@link TextBlock}'s having word wrap. * * Panels have no visual components of their own unless a {@link GraphObject.background} is specified * or separators are specified either as defaults for the whole Table Panel or on individual {@link RowColumnDefinition}s. * Panels can specify {@link padding}, to make the Panel larger including its background. Setting a padding * when the Panel is constrained in size will reduce the total area that it has to arrange its elements. Setting a {@link margin} * will not do this -- instead the Panel will expand in size. * * In addition to the {@link GraphObject} properties on elements that are only used by certain types of panels, * several Panel properties only apply to specific Panel types. * - Panels of {@link type} {@link Panel.Table} use the {@link rowCount}, {@link rowSizing}, {@link columnCount}, * {@link columnSizing}, {@link leftIndex}, {@link topIndex}, and all of the "default" separator properties. * - Panels of {@link type} {@link Panel.TableRow} and {@link Panel.TableColumn} do not act like regular GraphObjects, * instead they are only to be used immediately within a {@link Panel.Table}. They are pass-through containers * that hold elements for their parent table, and ignore their own scale and angle. * - Panels of {@link type} {@link Panel.Grid} use the {@link gridCellSize} and {@link gridOrigin} properties. * - Panels of {@link type} {@link Panel.Viewbox} use the {@link viewboxStretch} property. * - Panels of {@link type} {@link Panel.Graduated} use the {@link graduatedMin}, {@link graduatedMax}, * {@link graduatedTickUnit}, and {@link graduatedTickBase} properties. * *

* For live examples of all Panel types, see the Introduction page on Panels. * *

Data Binding

* * Panels also provide fundamental support for data binding. * When a diagram gets a new model or when a diagram's model is augmented with additional data, * the diagram automatically creates a new Node or Link whose {@link data} property refers to the corresponding * node data or link data object. *

* For more discussion of data binding, please read the Introduction page on Models * and Data Binding. * * Panels provide support for automatically creating elements within the Panel based on items in a JavaScript Array. * This is achieved by setting or binding the {@link itemArray} property, which acts in a manner similar * to the {@link Model.nodeDataArray} property. * You can supply an {@link itemTemplate}, which must itself be a simple Panel, which is copied to create the element * in this container Panel corresponding to an item in the itemArray. * This property is analogous to the {@link Diagram.nodeTemplate} property, although for the diagram the * template must be a {@link Node}, {@link Group}, or simple {@link Part}. * * Much like the {@link Diagram.nodeTemplateMap}, Panel's {@link itemTemplateMap} supports having multiple templates, * so that the actual structure of the element created for a data item can be chosen dynamically. * Just as the {@link Model.nodeCategoryProperty} determines which template in the {@link Diagram.nodeTemplateMap} * is copied to create a {@link Node}, the {@link itemCategoryProperty} names the data property whose value * chooses the Panel in the itemTemplateMap to copy for the item. * * When binding the {@link itemArray} property, it is commonplace to set {@link Model.copiesArrays} and * {@link Model.copiesArrayObjects} properties to true, so that when a node is copied, the item Array and its * contents are copied, not shared. Or more generally, to customize the model's copying processes, you * can supply a custom {@link Model.copyNodeDataFunction}. *

* For more discussion and examples of item arrays, please read the Introduction page on Item Arrays. */ export class Panel extends GraphObject { /** * Constructs an empty Panel of the given {@link type}. Default type is {@link Panel.Position}. * The panel type must be one of the {@link PanelLayout} static values such as {@link Panel.Position}. * The string value such as "Auto" may also be used. * * Usage example: * *```js * const p = new go.Panel("Auto", { * margin: 5, * background: "red" * }); * ``` * * @param type - a string or PanelLayout, such as "Horizontal" or {@link Panel.Vertical}. * If not supplied, the default Panel type is "Position". * @param init - Optional initialization properties. */ constructor(type?: PanelLayout | string, init?: Partial); /** * Constructs an empty Panel. Default type is {@link Panel.Position}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Creates a deep copy of this Panel and returns it. */ copy(): this; /** * Gets or sets the type of the Panel, which controls how the Panel's elements are measured and arranged. * The value must be an instance of {@link PanelLayout}. * * Predefined values include {@link Panel} instances of built-in PanelLayouts: * - {@link Panel.Position} * - {@link Panel.Vertical} * - {@link Panel.Horizontal} * - {@link Panel.Auto} * - {@link Panel.Spot} * - {@link Panel.Table} * - {@link Panel.Viewbox} * - {@link Panel.Link} (see also {@link Link}s, which are all Panels of type Link) * - {@link Panel.TableRow} * - {@link Panel.TableColumn} * - {@link Panel.Grid} * - {@link Panel.Graduated} * * The default value is {@link Panel.Position}. * * You must not modify this property once the Panel has been measured or the Panel has been added to another Panel. */ get type(): PanelLayout; set type(value: PanelLayout); /** * This read-only property returns an iterator over the collection of the {@link GraphObject}s that this panel manages. * * You can change the collection by calling {@link add}, {@link insertAt}, {@link remove}, or {@link removeAt}. * * You can also get direct access to individual elements by calling {@link elt}. */ get elements(): Iterator; /** * Gets or sets the space between this Panel's border and its content. * Unlike {@link GraphObject.margin}, padding expands the area inside of the Panel's border. * If this Panel's size is unconstrained, this will increase the size of the panel. * If this Panel's size is constrained, this will decrease the total area * for the Panel elements to arrange themselves. * * Unlike margin, increases in size due to padding are visually covered by the {@link GraphObject.background}. * * Padding cannot contain negative numbers. * The default value is a {@link Margin} of zero. * @see {@link GraphObject.margin} */ get padding(): MarginLike; set padding(value: MarginLike); /** * Gets or sets the default alignment spot of this Panel, used as * the alignment for an element when its {@link GraphObject.alignment} value is {@link Spot.Default}. * The default value is {@link Spot.Default}, which is interpreted by the Panel in whatever manner seems reasonable, * depending on the Panel type. */ get defaultAlignment(): Spot; set defaultAlignment(value: Spot); /** * Gets or sets the default stretch of this Panel, used as * the stretch for an element when its {@link GraphObject.stretch} value is {@link Stretch.Default}. * The default value is {@link Stretch.Default}, which typically resolves to {@link Stretch.None}. */ get defaultStretch(): Stretch; set defaultStretch(value: Stretch); /** * For "Table" Panels: Gets or sets the additional padding for rows and columns. * Padding is applied both before and after a row or column's contents. * @see {@link RowColumnDefinition.separatorPadding} * @see {@link defaultColumnSeparatorStrokeWidth} * @see {@link defaultRowSeparatorStrokeWidth} */ get defaultSeparatorPadding(): MarginLike; set defaultSeparatorPadding(value: MarginLike); /** * For "Table" Panels: Gets or sets the default stroke (color) for rows * provided a given row has a nonzero {@link RowColumnDefinition.separatorStrokeWidth}. * {@link RowColumnDefinition.separatorStroke} can override this default value. * The default value is null -- no line is drawn. * @see {@link defaultRowSeparatorStrokeWidth} * @see {@link defaultRowSeparatorDashArray} * @see {@link RowColumnDefinition.separatorStroke} * @see {@link defaultColumnSeparatorStroke} */ get defaultRowSeparatorStroke(): BrushLike; set defaultRowSeparatorStroke(value: BrushLike); /** * For "Table" Panels: Gets or sets the default stroke width for a row's separator. * {@link RowColumnDefinition.separatorStrokeWidth} can override this default value. * The default value is 1. Any new value must be a real, non-negative number. * @see {@link RowColumnDefinition.separatorStrokeWidth} * @see {@link defaultColumnSeparatorStrokeWidth} */ get defaultRowSeparatorStrokeWidth(): number; set defaultRowSeparatorStrokeWidth(value: number); /** * For "Table" Panels: Gets or sets the default dash array for a row's separator. * {@link RowColumnDefinition.separatorDashArray} can override this default value. * * Must be an array of positive numbers and zeroes, * or else null to indicate a solid line. * * For example, the array [5, 10] would create dashes of 5 pixels and spaces of 10 pixels. * * Setting an array with all zeroes will set the value to null. * * Default is null. * @see {@link RowColumnDefinition.separatorDashArray} * @see {@link defaultColumnSeparatorDashArray} */ get defaultRowSeparatorDashArray(): Array | null; set defaultRowSeparatorDashArray(value: Array | null); /** * For "Table" Panels: Gets or sets the default stroke (color) for columns * provided a given column has a nonzero {@link RowColumnDefinition.separatorStrokeWidth}. * {@link RowColumnDefinition.separatorDashArray} can override this default value. * The default value is null -- no line is drawn. * @see {@link defaultColumnSeparatorStrokeWidth} * @see {@link defaultColumnSeparatorDashArray} * @see {@link RowColumnDefinition.separatorStroke} * @see {@link defaultRowSeparatorStroke} */ get defaultColumnSeparatorStroke(): BrushLike; set defaultColumnSeparatorStroke(value: BrushLike); /** * For "Table" Panels: Gets or sets the default stroke width for a column's separator. * {@link RowColumnDefinition.separatorStrokeWidth} can override this default value. * The default value is 1. Any new value must be a real, non-negative number. * @see {@link RowColumnDefinition.separatorStrokeWidth} * @see {@link defaultRowSeparatorStrokeWidth} */ get defaultColumnSeparatorStrokeWidth(): number; set defaultColumnSeparatorStrokeWidth(value: number); /** * For "Table" Panels: Gets or sets the default dash array for a column's separator. * {@link RowColumnDefinition.separatorStrokeWidth} can override this default value. * * Must be an array of positive numbers and zeroes, * or else null to indicate a solid line. * * For example, the array [5, 10] would create dashes of 5 pixels and spaces of 10 pixels. * * Setting an array with all zeroes will set the value to null. * * Default is null. * @see {@link RowColumnDefinition.separatorDashArray} * @see {@link defaultRowSeparatorDashArray} */ get defaultColumnSeparatorDashArray(): Array | null; set defaultColumnSeparatorDashArray(value: Array | null); /** * For "Viewbox" Panels: Gets or sets how the panel will resize its content. * * Possible values are {@link ViewboxStretch.Uniform} and {@link ViewboxStretch.UniformToFill}. * The default is {@link ViewboxStretch.Uniform}. */ get viewboxStretch(): ViewboxStretch; set viewboxStretch(value: ViewboxStretch); /** * For "Grid" Panels: Gets or sets the distance between lines. * The units are in local coordinates. * The default is 10x10. Any new width or height must be a positive real number. */ get gridCellSize(): Size; set gridCellSize(value: Size); /** * For "Grid" Panels: Gets or sets an origin point for the grid cells. * The units are in local coordinates. * The default is (0,0). Any new value must use real numbers. */ get gridOrigin(): Point; set gridOrigin(value: Point); /** * For "Graduated" Panels: Gets or sets the minimum value represented. * Must be less than {@link graduatedMax}. The default is 0. */ get graduatedMin(): number; set graduatedMin(value: number); /** * For "Graduated" Panels: Gets or sets the maximum value represented. * Must be greater than {@link graduatedMin}. The default is 100. */ get graduatedMax(): number; set graduatedMax(value: number); /** * For "Graduated" Panels: This read-only property returns the range of values represented by the Panel. * * For example, a {@link graduatedMin} of 25 and {@link graduatedMax} of 75 would return 50. */ get graduatedRange(): number; /** * For "Graduated" Panels: Gets or sets the difference between two consecutive values marked by ticks. * Must be positive. The default is 10. */ get graduatedTickUnit(): number; set graduatedTickUnit(value: number); /** * For "Graduated" Panels: Gets or sets the base value which is marked with a tick. * The default is 0. */ get graduatedTickBase(): number; set graduatedTickBase(value: number); /** * Return an immediate child element whose {@link GraphObject.isPanelMain} is true, * or else just return the first child element. * @returns this may return null if there are no child elements */ findMainElement(): GraphObject | null; /** * Undocumented state for PanelLayouts */ get panelLayoutState(): any | null; /** * Undocumented state for PanelLayouts */ set panelLayoutState(value: any | null); /** * Search the visual tree starting at this Panel for a GraphObject * whose {@link GraphObject.name} is the given name. * * This does not recurse into the elements inside a Panel that holds elements for an {@link itemArray}. * @param name - The name to search for, using a case-sensitive string comparison. * @returns If no such named object can be found, this returns null. */ findObject(name: string): GraphObject | null; /** * Adds a number of GraphObjects to the end of this Panel's list of elements, visually in front of all of the other elements. * * If the element to be added is already in this Panel's list of elements, * the object is moved to the end of the list. * You cannot add a GraphObject to a Panel if that GraphObject is already in a different Panel. * @returns this Panel * @param elements - Any number of GraphObjects. */ add(...elements: Array): this; /** * Returns the GraphObject in this Panel's list of elements at the specified index. * @param idx */ elt(idx: number): GraphObject; /** * Adds a GraphObject to the Panel's list of elements at the specified index. * * If the element to be added is already in this Panel's list of elements, * the object is moved to the specified index. * You cannot add a GraphObject to a Panel if that GraphObject is already in a different Panel. * @param index * @param element - A GraphObject. */ insertAt(index: number, element: GraphObject): void; /** * Removes a GraphObject from this Panel's list of elements. * @param element - A GraphObject. */ remove(element: GraphObject): void; /** * Removes an GraphObject from this Panel's list of elements at the specified index. * @param idx */ removeAt(idx: number): void; /** * For "Table" Panels: This read-only property returns the number of rows. * This value is only valid after the Panel has been measured. */ get rowCount(): number; /** * For "Table" Panels: Gets the {@link RowColumnDefinition} for a particular row. * If you ask for the definition of a row at or beyond the {@link rowCount}, * it will automatically create one and return it. * * If this Panel is not a Table Panel, this method returns null. * @param idx - the non-negative zero-based integer row index. */ getRowDefinition(idx: number): RowColumnDefinition; /** * For "Table" Panels: Removes the {@link RowColumnDefinition} for a particular row. * * If this Panel is not a Table Panel, this method does nothing. * @param idx - the non-negative zero-based integer row index. */ removeRowDefinition(idx: number): void; /** * For "Table" Panels: This read-only property returns the number of columns. * This value is only valid after the Panel has been measured. */ get columnCount(): number; /** * For "Table" Panels: Gets the {@link RowColumnDefinition} for a particular column. * If you ask for the definition of a column at or beyond the {@link columnCount}, * it will automatically create one and return it. * * If this Panel is not a Table Panel, this method returns null. * @param idx - the non-negative zero-based integer column index. */ getColumnDefinition(idx: number): RowColumnDefinition; /** * For "Table" Panels: Removes the {@link RowColumnDefinition} for a particular row. * * If this Panel is not a Table Panel, this method does nothing. * @param idx - the non-negative zero-based integer row index. */ removeColumnDefinition(idx: number): void; /** * For "Table" Panels: Sets the given {@link RowColumnDefinition}. * If the row or column definition does not exist on the Panel, this will create it. * If it already exists on the Panel, this will copy the properties of the given RowColumnDefinition * onto that RowColumnDefinition. * @since 2.3 * @param rowOrColumnDef - the non-negative zero-based integer column index. * @returns this Panel * @see {@link addRowDefinition} * @see {@link addColumnDefinition} */ addRowColumnDefinition(rowOrColumnDef: RowColumnDefinition): this; /** * For "Table" Panels: Sets the row {@link RowColumnDefinition} given by the index. * If the row definition does not exist on the Panel, this will create it. * If it already exists on the Panel, this will copy the properties of the given RowColumnDefinition options * onto that definition. * * This is a convenience method for {@link addRowColumnDefinition}. Instead of writing: * ```js * .addRowColumnDefinition(new go.RowColumnDefinition({ row: 2, height: 60 })) * ``` * * You can write: * * ```js * .addRowDefinition(2, { height: 60 }) * ``` * * @since 2.3 * @param rowIndex - the non-negative zero-based integer row index. * @param options - the initialization options passed to the RowColumnDefinition constructor. * @returns this Panel * @see {@link addColumnDefinition} * @see {@link addRowColumnDefinition} */ addRowDefinition(rowIndex: number, options: Partial): this; /** * For "Table" Panels: Sets the column {@link RowColumnDefinition} given by the index. * If the column definition does not exist on the Panel, this will create it. * If it already exists on the Panel, this will copy the properties of the given RowColumnDefinition options * onto that definition. * * This is a convenience method for {@link addRowColumnDefinition}. Instead of writing: * ```js * .addRowColumnDefinition(new go.RowColumnDefinition({ column: 2, width: 60 })) * ``` * * You can write: * * ```js * .addColumnDefinition(2, { width: 60 }) * ``` * * @since 2.3 * @param colIndex - the non-negative zero-based integer column index. * @param options - the initialization options passed to the RowColumnDefinition constructor. * @returns this Panel * @see {@link addRowDefinition} * @see {@link addRowColumnDefinition} */ addColumnDefinition(colIndex: number, options: Partial): this; /** * For "Table" Panels: Gets or sets how this Panel's rows deal with extra space. * Valid values are {@link Sizing} values. * The default is {@link Sizing.ProportionalExtra}. * @see {@link RowColumnDefinition.sizing} * @see {@link columnSizing} */ get rowSizing(): Sizing; set rowSizing(value: Sizing); /** * For "Table" Panels: Gets or sets how this Panel's columns deal with extra space. * Valid values are {@link Sizing} values. * The default is {@link Sizing.ProportionalExtra}. * @see {@link RowColumnDefinition.sizing} * @see {@link rowSizing} */ get columnSizing(): Sizing; set columnSizing(value: Sizing); /** * For "Table" Panels: Gets or sets the first row that this Panel displays. * The default value is 0. * @see {@link leftIndex} */ get topIndex(): number; set topIndex(value: number); /** * For "Table" Panels: Gets or sets the first column that this Panel displays. * The default value is 0. * @see {@link topIndex} */ get leftIndex(): number; set leftIndex(value: number); /** * For "Table" Panels: Returns the row at a given y-coordinate in local coordinates, * or -1 if there are no RowColumnDefinitions for this Table Panel or if the argument is negative. * Call {@link GraphObject.getLocalPoint} to convert a Point in document coordinates into * a Point in local coordinates. * * @param y * @returns a zero-based integer * @see {@link findColumnForLocalX} */ findRowForLocalY(y: number): number; /** * For "Table" Panels: Returns the cell at a given x-coordinate in local coordinates, * or -1 if there are no RowColumnDefinitions for this Table Panel or if the argument is negative. * Call {@link GraphObject.getLocalPoint} to convert a Point in document coordinates into * a Point in local coordinates. * * @param x * @returns a zero-based integer * @see {@link findRowForLocalY} */ findColumnForLocalX(x: number): number; /** * For "Graduated" Panels: Returns the point that corresponds with a value, in the panel's coordinates. * * If the value provided is not within the {@link graduatedMin} and {@link graduatedMax}, * it will be constrained to within those values. * * If this Panel is not a Graduated Panel, this method returns Point(NaN, NaN). * @param val - a value between {@link graduatedMin} and {@link graduatedMax} * @param result - an optional Point that is modified and returned * @see {@link graduatedValueForPoint} */ graduatedPointForValue(val: number, result?: Point): Point; /** * For "Graduated" Panels: Returns the value that corresponds with the given Point. * The Point must be in the panel's coordinates. * The value returned will be in the Graduated Panel's range. * * If this Panel is not a Graduated Panel, this method returns NaN. * @param pt - a Point in the Graduated Panel's coordinates * @see {@link graduatedPointForValue} */ graduatedValueForPoint(pt: Point): number; /** * Gets or sets the optional model data to which this panel is data-bound. * The data must be a JavaScript Object if this is a {@link Part}. * The data can be any JavaScript value if this is a {@link Panel} created for * an item in an Array that was data-bound by the {@link itemArray} property. * The default value is null. * * Setting it to a new value automatically calls {@link updateTargetBindings} * in order to assign new values to all of the data-bound GraphObject properties. * * Once you set this property you cannot add, remove, or modify any data bindings * on any of the GraphObjects in the visual tree of this Panel, including on * this panel itself. * * You should not modify this property on a {@link Part} that is created automatically * to represent model data, nor on a {@link Panel} that is created automatically for a data item * in the containing Panel's {@link Panel.itemArray}. * Call {@link Model.removeNodeData} and {@link Model.addNodeData} if you want to replace * this Part with another one, or call {@link Model.removeArrayItem} and {@link Model.insertArrayItem} * if you want to replace this Panel with another one. * * Although you might not be able to replace this data value if this Part was created * automatically by the Diagram, you can still modify that data object's properties. * Call the appropriate Model method for changing properties that affect the structure of the diagram. * Call {@link Model.setDataProperty} for changing other properties that may be the sources * of {@link Binding}s on {@link GraphObject} properties that are in the visual tree of this panel/part. */ get data(): any | null; set data(value: any | null); /** * Gets the index of this Panel's data if it was created to represent an item in its containing Panel's {@link Panel.itemArray}. * The default value is NaN. * * This is only set internally by code such as {@link rebuildItemElements} or {@link Model.insertArrayItem} * when building or shifting Panel representing items * in the Panel whose {@link Panel.itemArray} was set or bound to an Array of value. * * This property can be used in data bindings within the item template to produce values * that depend on its position in the item Array. * For example: * ```js * new go.Panel('Vertical', { // the item Panel * itemTemplate: * new go.Panel() * // set Panel.background to a color based on the Panel.itemIndex * // bound to this Panel itself, not to the Panel.data item * .bindObject("background", "itemIndex", * // using this conversion function * i => (i%2 === 0) ? "lightgreen" : "lightyellow" * ) * .add( * new go.TextBlock() // a trivial item template, just showing some text * .bind("text", '') // sets TextBlock.text = data.items[itemIndex] * ) * }) * .bind("itemArray", "items") * ``` * * The main element of a Spot or Auto or Link Panel, or the first TableRow or TableColumn element of a Table Panel * whose {@link isPanelMain} property is true, will not have this property set to a number, * because it will not have been created by {@link rebuildItemElements}. * @readonly */ get itemIndex(): number; set itemIndex(value: number); /** * (undocumented) * Collect all of the Bindings in the visual tree, freeze them, * and make sure there is a name association to the target object, * so that they can be found in each copy of the visual tree. */ freezeBindings(): this; /** * Make a deep copy of this Panel and allow it to be used as a template. * This makes copies of Bindings, unlike the regular `copy()` method. * Pass true as the argument in order to freeze the Bindings, * allowing it to operate efficiently as a template. * A false value (which is the default) allows further additions/modifications * of the bindings in the copied Panel. * @since 2.2 * @param freeze - whether to freeze the Bindings in the copy; default is false */ copyTemplate(freeze?: boolean): this; /** * Re-evaluate all data bindings on this panel, * in order to assign new property values to the {@link GraphObject}s in this visual tree * based on this object's {@link data} property values. * * It is better to call {@link Model.setDataProperty} to modify data properties, * because that will both record changes for undo/redo and will update all bindings * that may depend on that property. * * This method does nothing if {@link data} is null. * @param srcprop - An optional source data property name: * when provided, only evaluates those {@link Binding}s that use that particular property; * when not provided or when it is the empty string, all bindings are evaluated. * @see {@link Model.updateTargetBindings} */ updateTargetBindings(srcprop?: string): void; /** * Gets or sets a JavaScript Array of values or objects, each of which will be represented * by a {@link Panel} as elements in this Panel. * Replacing this array results all of this panel's child objects being replaced with * a copy of the {@link Panel} found in {@link itemTemplateMap} for each particular * item in the Array. * * Because the software does not receive any notifications when an Array is modified, * any insertions or removals or replacements of data in the Array will not be noticed * unless you call {@link Model.insertArrayItem} or {@link Model.removeArrayItem}. * You may also reset this property to its current value (the modified Array) or * call {@link updateTargetBindings}, if there is a {@link Binding} whose target is this property. * * When binding this property, it is commonplace to set {@link Model.copiesArrays} and * {@link Model.copiesArrayObjects} properties to true, so that when a node is copied, * the item Array and its contents are copied, not shared. * Or more generally, to customize the model's copying processes, you can supply a custom * {@link Model.copyNodeDataFunction} and perhaps a {@link GraphLinksModel.copyLinkDataFunction}. * * Any JavaScript Object that is in this Array must only appear once in the array * and must not appear in any other {@link Panel.itemArray}s. * Use {@link findItemPanelForData} to find the data-bound Panel created for an Object in this panel's item Array. * * Non-Object values in an item Array may appear multiple times. * An item Array may be shared by multiple Panels. * * Item Arrays should not be used with Grid Panels or Graduated Panels as they may not have nested Panels. */ get itemArray(): Array | null; set itemArray(value: Array | null); /** * Return the {@link Panel} that was made for a particular data object in this panel's {@link itemArray}. * If this returns a Panel, its {@link data} property will be the argument data object, * and its containing {@link GraphObject.panel} will be this panel. * @param data - must be a non-null Object, not a string or a number or a boolean or a function * @returns or null if not found */ findItemPanelForData(data: ObjectData): Panel | null; /** * Create and add new GraphObjects corresponding to and bound to the data in the {@link itemArray}, * after removing all existing elements from this Panel. * This method is automatically called when replacing the {@link itemArray} value, * or when changing the value of {@link itemTemplate} or {@link itemTemplateMap}. * * This uses {@link itemCategoryProperty} to determine the category for an item data. * That string is used to look up a template in {@link itemTemplateMap}. * The resulting template (which is also a Panel) is copied, added to this panel, * and its {@link itemIndex} is set to its index in that Array. * That new child Panel is then data-bound to that Array item by setting its {@link data}. * * If {@link itemArray} is null, this method just removes all elements from this panel. * Actually, if this Panel {@link type} is "Spot", "Auto", or "Link", the very first element * is always kept by this method. * Also, if this Panel type is "Table", and if the first element is a "TableRow" or "TableColumn" Panel * whose {@link isPanelMain} property is set to true, that first element will be kept too. * That is useful for defining literal TableRow headers in Table panels, when the header information * is not kept as the first item in the itemArray. * * It is wasteful to call this method after making some model data changes. * It is better to call {@link Model.setDataProperty}, {@link Model.addArrayItem}, * {@link Model.insertArrayItem}, or {@link Model.removeArrayItem}, or other model methods. * Not only do those methods update efficiently, they also preserve unbound state and support undo/redo. */ rebuildItemElements(): void; /** * Gets or sets the default {@link Panel} template used as the archetype * for item data that are in {@link itemArray}. * * Setting this property just modifies the {@link itemTemplateMap} * by replacing the entry named with the empty string. * Any new value must be a {@link Panel} but not a {@link Part}. * By default this property is null. * * {@link GraphObject.copy} when copying a panel will share the {@link itemTemplateMap} * between the original panel and the copied panel. */ get itemTemplate(): Panel; set itemTemplate(value: Panel); /** * Gets or sets a {@link Map | go.Map} mapping template names to {@link Panel}s. * One of these Panels is copied for each item data that is in the {@link itemArray}. * Replacing this map will automatically rebuild all of the elements in this Panel. * * By default this property is null. * All values in the {@link Map | go.Map} must be {@link Panel}s but not {@link Part}s. * * If you modify this {@link Map | go.Map}, by replacing a {@link Panel} or by adding or * removing a map entry, you need to explicitly call {@link rebuildItemElements} afterwards. * * {@link GraphObject.copy} when copying a panel will share the {@link itemTemplateMap} * between the original panel and the copied panel. */ get itemTemplateMap(): Map | null; set itemTemplateMap(value: Map | null); /** * Gets or sets the name of the item data property that returns a string describing that data's category, * or a function that takes an item data object and returns that string; * the default value is the name 'category'. * This is used to distinguish between different * kinds of items in the {@link itemArray}. * * The name must not be null. * If the value is an empty string, the category is assumed to be an empty string, * the default category name, for all item data objects. * You must not change this property when the {@link itemArray} already has a value. */ get itemCategoryProperty(): string | ((a: any) => string); set itemCategoryProperty(value: string | ((a: any) => string)); /** * For {@link Spot} Panels: Gets or sets whether this Panel's main element clips instead of fills. * This assumes that the main element is a Shape. * The main Shape element will not paint its stroke, if it has any, * and should have its Shape.strokeWidth set to `0`. * * Since 2.2: For {@link Group}s: Gets or sets whether this Group's Placeholder clips its member nodes. * For compatibility, if the Group is a {@link Spot} Panel, it will not clip its members. * * When this property is `true`, the Spot panel will size itself to be the *intersection* of the main element bounds and * all other elements' bounds, rather than the union of these bounds. */ get isClipping(): boolean; set isClipping(value: boolean); /** * For "Horizontal" and "Vertical" Panels: gets or sets whether this Panel arranges its contents from the * typical side (left and top, respectively), or the opposite side (right and bottom, respectively). * * The default value is false. */ get isOpposite(): boolean; set isOpposite(value: boolean); /** * Gets or sets whether this Panel or any GraphObject inside the panel actually responds to user click events. * It may be used as a Binding target. * See how this property is used in Buttons.js. * * This property does not have any effect on picking ("hit-testing") -- that behavior is implemented * by the {@link GraphObject.pickable} property. * When this property is false, non-click events may still occur on this panel or on objects within this panel. * This property is normally only used for Panels that are {@link GraphObject.isActionable}. * * Call {@link GraphObject.isEnabledObject} to decide whether a particular object can be clicked. * @see {@link GraphObject.isEnabledObject} * @see {@link GraphObject.enabledChanged} * @see {@link GraphObject.isActionable} * @see {@link GraphObject.pickable} */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * For Panels which are elements of Spot Panels: Gets or sets the name * of this Panel's element that should be used as the alignment object instead of this Panel. * * This allows Spot Panels to align objects that are nested in the element tree of its own elements. */ get alignmentFocusName(): string; set alignmentFocusName(value: string); /** * Register a PanelLayout. This is called when making new Panel types. * See the PanelLayout sample for an example. * @param layoutName - Panel name * @param layout - instance of the PanelLayout * @since 2.0 */ static definePanelLayout(layoutName: string, layout: PanelLayout): void; /** * This static predicate is true if and only if {@link Panel.definePanelLayout} has been called on the given name. * @param name */ static isBuilderDefined(name: string): boolean; /** * Returns a 'Position' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Position: PanelLayout; /** * Returns a 'Horizontal' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Horizontal: PanelLayout; /** * Returns a 'Vertical' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Vertical: PanelLayout; /** * Returns a 'Spot' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Spot: PanelLayout; /** * Returns a 'Auto' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Auto: PanelLayout; /** * Returns a 'Table' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Table: PanelLayout; /** * Returns a 'Viewbox' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Viewbox: PanelLayout; /** * Returns a 'TableRow' PanelLayout, a possible value for {@link Panel.type}. */ static readonly TableRow: PanelLayout; /** * Returns a 'TableColumn' PanelLayout, a possible value for {@link Panel.type}. */ static readonly TableColumn: PanelLayout; /** * Returns a 'Link' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Link: PanelLayout; /** * Returns a 'Grid' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Grid: PanelLayout; /** * Returns a 'Graduated' PanelLayout, a possible value for {@link Panel.type}. */ static readonly Graduated: PanelLayout; } /** * This enumeration specifies how rows and columns deal with extra space. * Used for {@link RowColumnDefinition.sizing}. * @since 3.0 */ export declare enum Sizing { /** * The default, which resolves to {@link None} or else * the Table Panel's rowSizing and columnSizing if present. */ Default = 1, /** * The default if none is specified on the Table Panel's rowSizing and columnSizing. */ None = 2, /** * If a Table Panel is larger than all the rows/columns then this * grants this row/column and any others with the same value the extra space, apportioned proportionally between them. */ ProportionalExtra = 3 } /** * The RowColumnDefinition class describes constraints on a row or a column * in a {@link Panel} of type "Table". * It also provides information about the actual layout after the * Table Panel has been arranged. */ export class RowColumnDefinition { /** * You can use this constructor with {@link Panel.addRowColumnDefinition} to add * RowColumnDefinitions to Table Panels. * * Calls to {@link Panel.getRowDefinition} or {@link Panel.getColumnDefinition} * will automatically create and remember a RowColumnDefinition for you. * @param init - Optional initialization properties. These can include `row` or `column` index numbers as a convenience * instead of setting {@link isRow} and {@link index}. */ constructor(init?: Partial); /** * @deprecated See {@link Sizing.Default}. */ static readonly Default = Sizing.Default; /** * @deprecated See {@link Sizing.None}. */ static readonly None = Sizing.None; /** * @deprecated See {@link Sizing.ProportionalExtra}. */ static readonly ProportionalExtra = Sizing.ProportionalExtra; /** * (undocumented) * Get the spacing at the top or left of the row or column. * @param first - the first row or column with an element in it * @see {@link computeEffectiveSpacing} */ computeEffectiveSpacingTop(first: number): number; /** * (undocumented) * Get the total spacing for a row or column. * * For a row, this would be the value of {@link Panel.defaultRowSeparatorStrokeWidth} or {@link RowColumnDefinition.separatorStrokeWidth}, * plus the top and bottom values of {@link Panel.defaultSeparatorPadding} or {@link RowColumnDefinition.separatorPadding}. */ computeEffectiveSpacing(): number; /** * This read-only property returns the {@link Panel} that this row or column definition is in. */ get panel(): Panel | null; /** * This read-only property is true when this describes a row instead of a column in the {@link panel}. * When this is true, the {@link height}, {@link minimum}, and {@link maximum} * all describe the row height. * Otherwise {@link width} and the other two properties describe the column width. */ get isRow(): boolean; set isRow(value: boolean); /** * This read-only property returns which row or column this RowColumnDefinition describes in the {@link panel}. * The value is a zero-based integer. * @see {@link Panel.findColumnForLocalX} * @see {@link Panel.findRowForLocalY} * @see {@link Panel.leftIndex} * @see {@link Panel.topIndex} * @see {@link position} */ get index(): number; set index(value: number); /** * Gets or sets the row height, in local coordinates. * This describes the row height if {@link isRow} is true; * otherwise this property is meaningless. * The value must be non-negative and finite. * * The default value is NaN, which means this row will get a height * that is just big enough to hold all of the objects in the row. * * Setting this value to a number will mean that all of the objects * of this {@link Panel} in this row will be allocated that * amount of row height. * Whether an object in the row is actually arranged to have that height * depends on whether the {@link GraphObject.stretch} stretches vertically. * @see {@link width} * @see {@link minimum} * @see {@link maximum} * @see {@link sizing} */ get height(): number; set height(value: number); /** * Gets or sets the column width, in local coordinates. * The size describes the column width if {@link isRow} is false; * otherwise this property is meaningless. * The value must be non-negative and finite. * * The default value is NaN, which means this column will get a width * that is just big enough to hold all of the objects in the column. * * Setting this value to a number will mean that all of the objects * of this {@link Panel} in this column will be allocated that * amount of column width. * Whether an object in the column is actually arranged to have that width * depends on whether the {@link GraphObject.stretch} stretches horizontally. * @see {@link height} * @see {@link minimum} * @see {@link maximum} * @see {@link sizing} */ get width(): number; set width(value: number); /** * Gets or sets the minimum row height or column width, in local coordinates. * The minimum describes the row height if {@link isRow} is true; * otherwise this describes the column width. * * The value must be non-negative and finite. * The default value is zero. * The arranged height of all objects in this row, * or the arranged width of all objects in this column, * will be no less than this value. * @see {@link width} * @see {@link height} * @see {@link maximum} * @see {@link sizing} */ get minimum(): number; set minimum(value: number); /** * Gets or sets the maximum row height or column width, in local coordinates. * The maximum describes the row height if {@link isRow} is true; * otherwise this describes the column width. * * The value must be non-negative. * The default value is Infinity. * The arranged height of all objects in this row, * or the arranged width of all objects in this column, * will be no greater than this value. * @see {@link width} * @see {@link height} * @see {@link minimum} * @see {@link sizing} */ get maximum(): number; set maximum(value: number); /** * Gets or sets a default alignment for elements that are in this row or column. * The value must be a {@link Spot}. * The default value is {@link Spot.Default}, so that this RowColumnDefinition * does not supply any alignment information for the row or column. * * When an element's {@link GraphObject.alignment} property is {@link Spot.Default}, * it gets the horizontal alignment from the element's column's {@link RowColumnDefinition} * and the vertical alignment from the element's row's RowColumnDefinition. * When that {@link RowColumnDefinition.alignment} property is also Default, * it takes the value from the table panel's {@link Panel.defaultAlignment} property. * @see {@link GraphObject.alignment} * @see {@link Panel.defaultAlignment} */ get alignment(): Spot; set alignment(value: Spot); /** * Gets or sets the default stretch for elements that are in this row or column. * The only accepted values are listed as constant properties of GraphObject: * {@link Stretch.None}, {@link Stretch.Fill}, {@link Stretch.Horizontal}, {@link Stretch.Vertical}, or {@link Stretch.Default}. * The default value is {@link Stretch.Default}, so that this RowColumnDefinition * does not supply any stretch information for the row or column. * * When an element's {@link GraphObject.stretch} property is {@link Stretch.Default}, * it gets the horizontal stretch from the element's column's {@link RowColumnDefinition} * and the vertical stretch from the element's row's RowColumnDefinition. * When that {@link RowColumnDefinition.stretch} property is also Default, * it takes the value from the table panel's {@link Panel.defaultStretch} property. * @see {@link GraphObject.stretch} * @see {@link Panel.defaultStretch} * @see {@link sizing} * @see {@link width} * @see {@link height} */ get stretch(): Stretch; set stretch(value: Stretch); /** * Gets or sets the additional padding for a particular row or column, in local coordinates. * Padding is applied on two sides - before and after a row or column's contents. * The {@link separatorStrokeWidth} comes before any padding {@link Margin.top} or {@link Margin.left}. * * The default value is null, so that this RowColumnDefinition * does not supply any padding information for the row or column. * There may still be some padding between rows and/or columns if {@link Panel.defaultSeparatorPadding} is non-zero. * @see {@link Panel.defaultSeparatorPadding} * @see {@link separatorStroke} * @see {@link separatorStrokeWidth} * @see {@link separatorDashArray} * @see {@link background} */ get separatorPadding(): MarginLike; set separatorPadding(value: MarginLike); /** * Gets or sets the stroke (color) for the separator line that is drawn before a particular row or column, * provided that row or column has a nonzero {@link separatorStrokeWidth}. * * The default value is null, so that this RowColumnDefinition * does not specify any brush for the separator line to draw before the row or column. * The line may still be drawn if the value of {@link Panel.defaultRowSeparatorStroke} or * {@link Panel.defaultColumnSeparatorStroke} is non-null. * * However, if no stroke color is specified, then no stroke width will be drawn, * even if the {@link separatorStrokeWidth} value is non-zero. * @see {@link Panel.defaultColumnSeparatorStroke} * @see {@link Panel.defaultRowSeparatorStroke} * @see {@link separatorPadding} * @see {@link separatorStrokeWidth} * @see {@link separatorDashArray} * @see {@link background} */ get separatorStroke(): BrushLike; set separatorStroke(value: BrushLike); /** * Gets or sets the stroke width for a particular row or column's separator line, in local coordinates. * * The default value is NaN, so that this RowColumnDefinition * does not supply any stroke width information for what is drawn before the row or column. * The separator line may still be drawn if {@link Panel.defaultRowSeparatorStroke} * or {@link Panel.defaultColumnSeparatorStroke} is a real number (they default to 1). * @see {@link Panel.defaultColumnSeparatorStrokeWidth} * @see {@link Panel.defaultRowSeparatorStrokeWidth} * @see {@link separatorPadding} * @see {@link separatorStroke} * @see {@link separatorDashArray} * @see {@link background} */ get separatorStrokeWidth(): number; set separatorStrokeWidth(value: number); /** * Gets or sets the dash array for dashing the separator line, provided this * row or column has a nonzero {@link RowColumnDefinition.separatorStrokeWidth} and non-null {@link RowColumnDefinition.separatorStroke}. * * Must be an array of positive numbers and zeroes, * or else null to indicate a solid line. * * For example, the array [5, 10] would create dashes of 5 pixels and spaces of 10 pixels. * * Setting an array with all zeroes will set the value to null. * * Default is null, so that this RowColumnDefinition * does not supply any stroke dash array information for what is drawn before the row or column. * The separator line may still be drawn using dashes if {@link Panel.defaultRowSeparatorDashArray} * or {@link Panel.defaultColumnSeparatorDashArray} is non-null. * @see {@link Panel.defaultColumnSeparatorDashArray} * @see {@link Panel.defaultRowSeparatorDashArray} * @see {@link separatorPadding} * @see {@link separatorStroke} * @see {@link separatorStrokeWidth} * @see {@link background} */ get separatorDashArray(): Array | null; set separatorDashArray(value: Array | null); /** * Gets or sets the background color for a particular row or column, * which fills the entire span of the row or column, including any separatorPadding. * * The default value is null, which means nothing is drawn in the background of the row or column. * @see {@link GraphObject.background} */ get background(): BrushLike; set background(value: BrushLike); /** * Determines whether or not the {@link background}, if there is one, is in front of or behind the separators. * * The default value is false -- any background is drawn behind any separator lines. */ get coversSeparators(): boolean; set coversSeparators(value: boolean); /** * Gets or sets how this row or column deals with a Table Panel's extra space. * The value must be a {@link Sizing} value. * The default value is {@link Sizing.Default}. * @see {@link Panel.columnSizing} * @see {@link Panel.rowSizing} * @see {@link actual} * @see {@link total} * @see {@link height} * @see {@link width} */ get sizing(): Sizing; set sizing(value: Sizing); /** * This read-only property returns the usable row height or column width, after arrangement, in local coordinates, * that objects in this row or column can be arranged within. * This does not include {@link separatorPadding} or {@link separatorStrokeWidth}, as {@link total} does. * * This value gives the row height if {@link isRow} is true; * otherwise this gives the column width. * The value is meaningless until after the Table Panel using this * RowColumnDefinition has been arranged. * @see {@link total} * @see {@link height} * @see {@link width} * @see {@link sizing} */ get actual(): number; set actual(value: number); /** * (undocumented) */ get measured(): number; set measured(value: number); /** * This read-only property returns the total arranged row height or column width, after arrangement, in local coordinates. * This value gives the {@link actual} size plus the {@link separatorPadding} and {@link separatorStrokeWidth}. * * This value gives the vertical space occupied by the row if {@link isRow} is true; * otherwise this gives the horizontal space occupied by the column. * The value is meaningless until after the Table Panel using this * RowColumnDefinition has been arranged. * @see {@link actual} * @see {@link height} * @see {@link width} * @see {@link sizing} */ get total(): number; /** * This read-only property returns the actual arranged row or column starting position, after arrangement, in local coordinates. * This value gives the Y position if {@link isRow} is true; * otherwise this gives the X position. * The value is meaningless until after the Table Panel using this * RowColumnDefinition has been arranged. * @see {@link Panel.findColumnForLocalX} * @see {@link Panel.findRowForLocalY} * @see {@link Panel.leftIndex} * @see {@link Panel.topIndex} * @see {@link index} */ get position(): number; set position(value: number); /** * Add a data-binding to this RowColumnDefinition for the given property names and optional conversion function. * * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the bound data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @param backconv - An optional conversion function to convert property values back to data values. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * @returns this RowColumnDefinition * @since 2.2 */ bind(targetprop: string, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion): this; /** * Add a data-binding of a property on this RowColumnDefinition to a property on a data object. * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param binding * @returns this RowColumnDefinition */ bind(binding: Binding): this; /** * This convenience function works like {@link GraphObject.bind}, creating a Binding, then also calls {@link Binding.makeTwoWay} on it. * These are equivalent: * ``` * .bind("text", "text", null, null) * .bindTwoWay("text") * ``` * As are these: * ``` * .bind("text", "someProp", null, null) * .bindTwoWay("text", "someProp") * ``` * * The first creates a two-way binding because specifying anything for the 4th argument (BackConversion) automatically * sets the {@link Binding.mode} to be {@link BindingMode.TwoWay}. However, it requires specifying the middle arguments, which may not be necessary. * * Read more about {@link Binding}s at the Introduction page about Data Bindings. * @param targetprop - A string naming the target property on this GraphObject. * This should not be the empty string. * This becomes the value of {@link Binding.targetProperty}. * @param sourceprop - A string naming the source property on the bound data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * This becomes the value of {@link Binding.sourceProperty}. * @param conv - An optional side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * This becomes the value of {@link Binding.converter}. * @param backconv - An optional conversion function to convert GraphObject property values back to data values. * Specifying this modifies the binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * This becomes the value of {@link Binding.backConverter}. * @returns this GraphObject * @since 3.0 */ bindTwoWay(targetprop: string | Binding, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion): this; /** * Add a {@link ThemeBinding} from a Theme property to a property on this RowColumnDefinition. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this RowColumnDefinition * @since 3.0 */ theme(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; /** * Add a {@link ThemeBinding} from a data property to a property on this RowColumnDefinition. * * This is a convenience function for {@link theme} that additionally calls {@link ThemeBinding.ofData} on the created binding. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this RowColumnDefinition * @since 3.0 */ themeData(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; /** * Add a {@link ThemeBinding} from a GraphObject property to a property on this RowColumnDefinition. * * This is a convenience function for {@link theme} that additionally calls {@link Binding.ofObject} on the created binding. * It passes the `objectSrcname` param to the {@link Binding.ofObject} call. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @param objectSrcname - the {@link GraphObject.name} of an element in the visual tree of the bound {@link Panel} * If not supplied, it uses the binding Panel as the source GraphObject. * @returns this RowColumnDefinition * @since 3.0 */ themeObject(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion, objectSrcname?: string): this; /** * Add a {@link ThemeBinding} from the shared {@link Model.modelData} to a property on this RowColumnDefinition. * * This is a convenience function for {@link theme} that additionally calls {@link Binding.ofModel} on the created binding. * * Read more about theming at the Introduction page about Themes. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the theme. * This should not be the empty string. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The theme source object to search for the source property. * If this argument is null or not supplied, the empty-string is used. * @param conv - An optional side-effect-free function converting the source property to the theme property name. * If the function is null or not supplied, no conversion takes place. * @param themeconv - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @returns this RowColumnDefinition * @since 3.0 */ themeModel(targetprop: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeconv?: TargetConversion): this; } /** * A Shape is a {@link GraphObject} that shows a geometric figure. * The {@link Geometry} determines what is drawn; * the properties {@link fill} and {@link stroke} * (and other stroke properties) determine how it is drawn. * * There are generally two types of shapes: Those that use a custom {@link Geometry} by setting * {@link Shape.geometry}, and those that receive an automatically generated Geometry using the value of * {@link figure}, {@link toArrow}, or {@link fromArrow}. An explicitly set Geometry always supersedes * the figure and arrowhead properties. * * Some created Shapes: * ```js * // A shape with the figure set to RoundedRectangle: * new go.Shape({ figure: "RoundedRectangle", fill: "lightgreen" }) * // Alternatively: * new go.Shape("RoundedRectangle" { fill: "lightgreen" }) * * // A shape with a custom geometry: * new go.Shape( * { geometry: go.Geometry.parse("M120 0 L80 80 0 50z") }) * * // A shape with a custom geometry, using geometryString: * new go.Shape( * { geometryString: "F M120 0 L80 80 0 50z", * fill: "lightgreen" }) * * // A common link template, using two shapes, * // the first for the link path and the second for the arrowhead * // The first shape in a link is special, its geometry is set by the Link's routing, * // so it does not need a geometry or figure set manually * myDiagram.linkTemplate = * new go.Link() * .add( * new go.Shape({ strokeWidth: 2, stroke: 'gray' }), * new go.Shape({ toArrow: "Standard", fill: 'gray', stroke: null }) * ); * ``` *

* You can see more custom geometry examples and read about geometryString * on the Geometry Path Strings Introduction page. * * When automatically generating a Shape {@link Geometry}, the value of {@link toArrow} takes precedence, * then {@link fromArrow}, then {@link figure}. If the value of {@link toArrow} or {@link fromArrow} is "None" * then it is ignored, and the "None" value of {@link figure} is identical to "Rectangle". * * All of the predefined figures are shown in the Shapes sample. * You can define your own named figures by calling the static function {@link Shape.defineFigureGenerator}. * Get a {@link Map | go.Map} of named figures by calling the static function {@link Shape.getFigureGenerators}. * * All of the predefined arrowheads are shown in the Arrowheads sample. * You can define your own named arrowheads by calling the static function {@link Shape.defineArrowheadGeometry}. * Get a {@link Map | go.Map} of named arrowheads by calling the static function {@link Shape.getArrowheadGeometries}. * * You can see a copy of all of the built-in arrowhead definitions in this file: Arrowheads.js. * * The Shape properties {@link parameter1}, and {@link parameter2} determine details of the * construction of some {@link figure} geometries. * Specifically, they often set the {@link spot1}, {@link spot2} for the Shape. * These spots determine the "inner area" of an Auto panel when a Shape is the main object. * See the Auto Panels section of the Panels Introduction page for more details. * * Shapes use their geometric bounds when determining hit testing, * but use rectangular bounds when participating in (panel) layouts. */ export class Shape extends GraphObject { /** * A newly constructed {@link Shape} has a default {@link figure} of "None", * which constructs a rectangular geometry, and is filled and stroked with a black brush. * * Common usage: * ```js * new go.Shape("RoundedRectangle", { * strokeWidth: 2, * stroke: "red", * fill: "yellow" * }) * ``` * * Or when using a custom {@link geometryString} instead of a {@link figure}: * * ```js * new go.Shape({ * fill: "red", * stroke: null, * width: 100, * height: 100, * // This SVG-style path creates a thick "+" figure: * geometryString: "F M2 1 h1 v1 h1 v1 h-1 v1 h-1 v-1 h-1 v-1 h1 z" * }) * ``` * * Also common is to set some or all of the Shape properties dynamically, * in the Node data, by way of bindings: * * ```js * // A Node used as the node template, holding a single shape * // The shape has many bindings * myDiagram.nodeTemplate = * new go.Node("Horizontal") * .add( * new go.Shape() * .bind("width") * .bind("height") * .bind("fill", "color") // binds the data.color to shape.fill * .bind("figure") * ); * * // It could be used with model data like this: * myDiagram.model = new go.GraphLinksModel( * [ * { key: "1", width: 150, height: 150, color: "red", figure: "Triangle" }, * { key: "2", width: 24, height: 24, color: "blue", figure: "Roundedrectangle" } * ]); * ``` * * @param figure - The shape's figure, a predefined geometry. * If no geometry is set then shapes will use the default figure of "None", a rectangle. * Common values are "Rectangle", "Ellipse", "RoundedRectangle". * @param init - Optional initialization properties. */ constructor(figure?: string, init?: Partial); /** * A newly constructed {@link Shape} has a default {@link figure} of "None", * which constructs a rectangular geometry, and is filled and stroked with a black brush. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Gets or sets the Shape's {@link Geometry} that defines the Shape's figure. * Setting a geometry is not necessary if a {@link figure} is specified, * as that will construct a geometry instead. * * Setting this geometry property will freeze the supplied Geometry. * * Setting this geometry property always overrides any set figure. * The default value is null. * @see {@link geometryString} */ get geometry(): Geometry | null; set geometry(value: Geometry | null); /** * When set, creates a {@link Geometry} and normalizes it from a given path string, * then sets the {@link geometry} property on this Shape and * set the {@link GraphObject.position} to the amount computed by normalization. * The property getter simply returns the toString value of the {@link geometry}, * or the empty string if there is no Geometry value. * * See the Geometry Path Strings Introduction page for examples. */ get geometryString(): string; set geometryString(value: string); /** * Gets or sets the whether the {@link GraphObject.position} of this shape denotes * the top-left corner of this shape in panel coordinates or the origin of this geometry's coordinate system. * Basically, this determines whether the {@link strokeWidth} affects the rendered location. * A true value allows multiple shapes to be positioned precisely in a "Position" Panel independent of the stroke width. * The default is false. */ get isGeometryPositioned(): boolean; set isGeometryPositioned(value: boolean); /** * Gets or sets the {@link Brush} or string that describes how the geometry is filled when drawn. * * The default value is "black", causing the shape to be filled with solid black. * Any valid CSS string can specify a solid color, and the {@link Brush} * class can be used to specify a gradient or pattern. * A null fill will mean no fill is drawn and the filled portion * of the Shape will not be pickable. * A "transparent" fill is useful when wanting to allow a shape to be pickable * without obscuring any other objects behind it. * More information about the syntax of CSS color strings is available at: * CSS colors (mozilla.org). * * The geometry is filled before the {@link stroke} is drawn. */ get fill(): BrushLike; set fill(value: BrushLike); /** * Gets or sets the {@link Brush} or string that describes how the geometry is drawn as if by a pen. * * The default value is "black", causing the shape to be outlined in black. * Any valid CSS string can specify a solid color, and the {@link Brush} * class can be used to specify a gradient or pattern. * A null stroke will mean no stroke is drawn. * A "transparent" stroke is useful when wanting to allow a shape to be pickable * without obscuring any other objects behind it. * More information about the syntax of CSS color strings is available at: * CSS colors (mozilla.org). * * The stroke is drawn after the geometry is filled with the {@link fill} Brush. */ get stroke(): BrushLike; set stroke(value: BrushLike); /** * Gets or sets the thickness of the stroke's pen. * * Value must be a real number greater than or equal to zero. * The default value is 1.0. * * A value of zero will cause the stroke not to be drawn. * However, Main Shapes of Link Selection Adornments with a strokeWidth of 0 * will inherit the strokeWidth from the Link's main Shape. * * The stroke width will affect the {@link GraphObject.measuredBounds} and {@link GraphObject.actualBounds} of this shape. * The stroke is drawn centered on the path of the geometry. */ get strokeWidth(): number; set strokeWidth(value: number); /** * Gets or sets the style for how the ends of the stroke's line are drawn. * The value must be one of "butt", "round", or "square". The default is "butt". * * For more information, see Stroke Line Cap (w3.org). */ get strokeCap(): ('butt' | 'round' | 'square'); set strokeCap(value: ('butt' | 'round' | 'square')); /** * Gets or sets the type of corner that will be drawn for a stroke at the intersection of two straight segments of the geometry. * The value must be one of "miter", "bevel", or "round". The default is "miter". * * For more information, see Stroke Line Join (w3.org). */ get strokeJoin(): ('miter' | 'bevel' | 'round'); set strokeJoin(value: ('miter' | 'bevel' | 'round')); /** * Gets or sets the style for the stroke's mitre limit ratio. * The value must be a real number greater than or equal to one. * The default is 10.0. * * For more information, see Stroke Miter Limit (w3.org). */ get strokeMiterLimit(): number; set strokeMiterLimit(value: number); /** * Gets or sets the dash array for creating dashed or dotted lines. * The value must be an array of positive numbers and zeroes, * or else null to indicate a solid line. * For example, the array [5, 10] would create dashes of 5 pixels and spaces of 10 pixels. * For more information, see Stroke Line Dash Array (w3.org). * * The default value is null, resulting in a line without dashes or dots. * Setting an array with all zeroes will set the value to null. */ get strokeDashArray(): Array | null; set strokeDashArray(value: Array | null); /** * Gets or sets the offset for dashed lines, used to start the drawing of the dash pattern with some space. * The value must be a real non-negative number. The default is zero. * * For more information, see Stroke Line Dash Offset (w3.org). */ get strokeDashOffset(): number; set strokeDashOffset(value: number); /** * Gets or sets the figure name, used to construct a {@link Geometry}. * The value must be a string. The default value is "None". * * The name can be any case but will always be canonicalized when set. For instance, * setting "roundedrectangle" will set the value of figure to "RoundedRectangle". * All of the predefined figures are shown in the Shapes sample. * * At most one of the following three properties may be set to a non-"None" value at the same time on the same shape: * {@link figure}, {@link toArrow}, {@link fromArrow}. * * You can define your own named figures by calling the static function {@link Shape.defineFigureGenerator}. */ get figure(): string; set figure(value: string); /** * Gets or sets the name of the kind of arrowhead that this shape should take * when this shape is an element of a {@link Link}. * Value must be a string. * * The default is "None", which means that this Shape is not an arrowhead, causing it to be the default Shape, a large filled Rectangle. * If you want to have an arrowhead Shape but sometimes not show an arrowhead, you can set or bind * the {@link GraphObject.visible} property, or you can set or bind this "toArrow" property to * be the empty string. * The arrowhead named "", an empty string, will display as nothing. * * The name can be any case but will always be canonicalized when set. For instance, * setting "opentriangle" will set the value of the arrowhead to "OpenTriangle". * All of the predefined arrowheads are shown in the Arrowheads sample. * * Setting this property may also set the {@link GraphObject.segmentIndex}, * {@link GraphObject.segmentOrientation}, and {@link GraphObject.alignmentFocus} properties. * This shape should be an element of a {@link Link}. * * At most one of the following three properties may be set to a non-"None" value at the same time on the same shape: * {@link figure}, {@link toArrow}, {@link fromArrow}. * * You can define your own named arrowheads by calling the static function {@link Shape.defineArrowheadGeometry}. * * You can see a copy of all of the built-in arrowhead definitions in this file: Arrowheads.js. */ get toArrow(): string; set toArrow(value: string); /** * Gets or sets the name of the kind of arrowhead that this shape should take * when this shape is an element of a {@link Link}. * Value must be a string. * For bi-directional links the arrowhead name often starts with "Backward...". * * The default is "None", which means that this Shape is not an arrowhead, causing it to be the default Shape, a large filled Rectangle. * If you want to have an arrowhead Shape but sometimes not show an arrowhead, you can set or bind * the {@link GraphObject.visible} property, or you can set or bind this "toArrow" property to * be the empty string. * The arrowhead named "", an empty string, will display as nothing. * * The name can be any case but will always be canonicalized when set. For instance, * setting "opentriangle" will set the value of the arrowhead to "OpenTriangle". * All of the predefined arrowheads are shown in the Arrowheads sample. * * Setting this property may also set the {@link GraphObject.segmentIndex}, * {@link GraphObject.segmentOrientation}, and {@link GraphObject.alignmentFocus} properties. * This shape should be an element of a {@link Link}. * * At most one of the following three properties may be set to a non-"None" value at the same time on the same shape: * {@link figure}, {@link toArrow}, {@link fromArrow}. * * You can define your own named arrowheads by calling the static function {@link Shape.defineArrowheadGeometry}. * * You can see a copy of all of the built-in arrowhead definitions in this file: Arrowheads.js. */ get fromArrow(): string; set fromArrow(value: string); /** * Gets or sets the top-left Spot used by some {@link Panel}s for determining where in the shape other objects may be placed. * The value is normally {@link Spot.Default}, but you may want to set it to override the value that many {@link figure}s use. */ get spot1(): Spot; set spot1(value: Spot); /** * Gets or sets the bottom-right Spot used by some {@link Panel}s for determining where in the shape other objects may be placed. * The value is normally {@link Spot.Default}, but you may want to set it to override the value that many {@link figure}s use. */ get spot2(): Spot; set spot2(value: Spot); /** * Gets or sets a property for parameterizing the construction of a {@link Geometry} from a figure. * The meaning of this property depends on the particular figure. * The value must be a number; the default value is NaN. */ get parameter1(): number; set parameter1(value: number); /** * Gets or sets a property for parameterizing the construction of a {@link Geometry} from a figure. * The meaning of this property depends on the particular figure. * The value must be a number; the default value is NaN. */ get parameter2(): number; set parameter2(value: number); /** * This read-only property returns the natural bounds of this Shape as determined by its {@link geometry}'s bounds. * The bounds will always include the (0,0) point. * If the {@link desiredSize} is set, it returns a {@link Rect} with the {@link desiredSize}. If no geometry is available, * and no {@link desiredSize} is set, this may have NaN values for the width and height. */ get naturalBounds(): Rect; /** * Gets or sets a {@link GraphObject} that is drawn repeatedly along the path of the stroke of this shape. * This property may be set to a shared GraphObject; the GraphObject should not belong to any Panel. * Note that data bindings do not work in such shared GraphObjects, because they are not part of the visual tree. * The default value is null, causing no object to be drawn repeatedly. * * Typically the object is a small {@link Shape} or a {@link Picture}. * The larger the object is the worse the results will be, especially if the stroke has short segments or sharp curves. * The pathPattern object is not part of the measured bounds of the Shape, it is a cosmetic element only. * * The stroke is always drawn normally -- having a value for this property will draw the value along the stroke as well, * so it is commonplace to set the {@link stroke} to "transparent" and the {@link strokeWidth} to be as wide as * the height of the GraphObject being drawn along the stroke. * * Examples of path patterns can be seen in the Relationships sample. * * This property is ignored by the Shapes in "Grid" or "Graduated" Panels. */ get pathPattern(): GraphObject | null; set pathPattern(value: GraphObject | null); /** * Gets or sets how the shape's geometry is proportionally created given its computed size. * Possible values are {@link GeometryStretch.None}, {@link GeometryStretch.Fill}, {@link GeometryStretch.Uniform}, and {@link GeometryStretch.Default}. * The default is {@link GeometryStretch.Default}, which resolves to {@link GeometryStretch.Fill} for most figures, though * some regular figures such as "Circle" and "Square" default to {@link GeometryStretch.Uniform}. */ get geometryStretch(): GeometryStretch; set geometryStretch(value: GeometryStretch); /** * Gets or sets how frequently this shape should be drawn within a "Grid" or "Graduated" {@link Panel}, * in multiples of the {@link Panel.gridCellSize} or {@link Panel.graduatedTickUnit}. * The default is 1. Any new value must be a positive integer. */ get interval(): number; set interval(value: number); /** * Gets or sets the fractional distance along the main shape of a "Graduated" {@link Panel} at which this kind of tick should start. * The default is 0. Any new value should range from 0 to 1. */ get graduatedStart(): number; set graduatedStart(value: number); /** * Gets or sets the fractional distance along the main shape of a "Graduated" {@link Panel} at which this kind of tick should end. * The default is 1. Any new value should range from 0 to 1. */ get graduatedEnd(): number; set graduatedEnd(value: number); /** * Gets or sets the function to determine which values along a "Graduated" {@link Panel} will be skipped. * The default is null and doesn't skip any ticks. * * The function takes a number argument, a value between {@link Panel.graduatedMin} and {@link Panel.graduatedMax}, * and this Shape. * The function will return a boolean, whether the tick will be skipped at the value of the argument. * * Note that the second argument is the Shape, *not* a particular tick that would be rendered at the given value. * The function, if supplied, must not have any side-effects. * @since 2.0 */ get graduatedSkip(): ((val: number, shape: Shape) => boolean) | null; set graduatedSkip(value: ((val: number, shape: Shape) => boolean) | null); /** * This static function returns a read-only Map of named geometry generators. * The keys are figure names. * The values are either string synonyms for other figure names, or functions * that take a {@link Shape} and a width and a height and return a {@link Geometry}. * * The predefined shape figures can be seen in the Shapes sample. */ static getFigureGenerators(): Map Geometry)>; /** * This static function defines a named figure geometry generator for Shapes. * Once this is called one can use the name as a value for {@link Shape.figure}. * * The first argument is the new figure name and must be a non-empty string that starts with a capital letter and that is not "None". * * If the second argument is a string this call defines a synonym for an existing figure generator. * Do not define cycles of synonyms -- the behavior will be undefined. * * If the second argument is a function, * the {@link Geometry} generator function's first argument is the {@link Shape} for which the function is producing a Geometry. * But this Shape argument may be null in some circumstances. * The second and third arguments are the desired width and height. * These will always be finite non-negative numbers. * The function may look at the {@link Shape.parameter1} and {@link Shape.parameter2} properties, which may be NaN, * to decide what geometry to create for the figure given its intended width and height. * * The function must return a Geometry; you may want to set {@link Geometry.spot1} and {@link Geometry.spot2} on it * to indicate where content should be placed within the figure when using an "Auto" Panel. * For some figures you may also want to set {@link Geometry.defaultStretch} to {@link GeometryStretch.Uniform} * in order to maintain the geometry's aspect ratio within the Shape. * * Generated figures must create a Geometry that is not larger than the supplied width and height. * Doing so is an error that may result in unexpected appearances or behaviors. * @param name - a capitalized figure name ("RoundedRectangle"); must not be "" or "None" * @param func - A function that takes (Shape,width,height) and returns a Geometry, * or an existing figure generator name for which the new name will be a synonym. */ static defineFigureGenerator(name: string, func: string | ((shape: Shape, width: number, height: number) => Geometry)): void; /** * This static predicate is true if and only if {@link Shape.defineFigureGenerator} has been called on the given name. * @param name */ static isFigureDefined(name: string): boolean; /** * This static function returns a read-only Map of named arrowhead geometries. * The keys are arrowhead names. * The values are {@link Geometry} objects. * * The predefined arrowheads can be seen in the Arrowheads sample. */ static getArrowheadGeometries(): Map; /** * This static function defines a named arrowhead geometry. * Once this is called one can use the name as a value for {@link Shape.toArrow} or {@link Shape.fromArrow}. * * The first argument is the new arrowhead name and must be a non-empty string that starts with a capital letter and that is not "None". * * If the second argument is a string, it is converted into a {@link Geometry} by calling * `go.Geometry.parse(pathstr, false)`, * which may throw an error if there are problems with the syntax of the string. * @param name - a capitalized arrowhead name ("OpenTriangle"); must not be "" or "None" * @param pathstr - a {@link Geometry} or a Geometry path string, e.g. "m 0,0 l 8,4 -8,4" */ static defineArrowheadGeometry(name: string, pathstr: Geometry | string): void; /** * This static predicate is true if and only if {@link Shape.defineArrowheadGeometry} has been called on the given name. * @param name */ static isArrowheadDefined(name: string): boolean; } /** * This enumeration specifies possible values for {@link TextBlock.wrap}. * @since 3.0 */ export declare enum Wrap { /** * The TextBlock will not wrap its text. */ None = 0, /** * The TextBlock will wrap text, making the width of the TextBlock equal to the width of the longest line. */ Fit = 1, /** * The TextBlock will wrap text and the width of the TextBlock will be the desiredSize's width, if any. */ DesiredSize = 2, /** * The TextBlock will attempt to wrap at each character, allowing breaks within "words." */ BreakAll = 3 } /** * This enumeration specifies possible values for {@link TextBlock.overflow}. * @since 3.0 */ export declare enum TextOverflow { /** * The TextBlock will clip if the width is too small to display all text. */ Clip = 0, /** * The TextBlock will display an ellipsis if the width is too small to display all text. */ Ellipsis = 1 } /** * This enumeration specifies possible values for {@link TextBlock.formatting}. * @since 3.0 */ export declare enum TextFormat { /** * The TextBlock will *not* automatically trim any whitespace at the start or end of each line of text. * This can be useful if your text is preformatted. */ Trim = 0, /** * The TextBlock will automatically trim any whitespace at the start or end of each line of text. */ None = 1 } /** * A TextBlock is a {@link GraphObject} that displays a {@link text} string in a given {@link font}. * * The size and appearance of the text is specified by {@link font}, * which takes a well-formed CSS string as its value. * The order of the CSS properties given is important for cross-browser compatibility, * and should be given in this order: * * "font-style font-variant font-weight font-size font-family" * * For example, "Italic small-caps bold 32px Georgia, Serif" is a valid font string * using every CSS font property. Note that not all browsers may support every property. * * Text is drawn using the {@link stroke} brush, which may be any CSS color string or a {@link Brush}. * * Some created TextBlocks: * ```js * // A TextBlock with text and stroke properties set: * new go.TextBlock({ text: "Hello World", stroke: "gray" }) * // Alternatively: * new go.TextBlock("Hello World", { stroke: "gray" }) * ``` * * TextBlocks typically receive a natural size based on their text and font strings, * but often a width is given in order to cause the text to wrap at a certain place. * In order for wrapping to occur, the {@link wrap} property must not be {@link Wrap.None}. * * TextBlocks can be edited by users using the {@link TextEditingTool}. * The {@link HTMLInfo} that a given TextBlock uses as its text editor can be customized * by setting the {@link textEditor} property. For an example of custom text editing tool use, * see the Custom TextEditingTool Sample. *

* For examples of TextBlock possibilities and functionality, * see the Introduction page on TextBlocks. */ export class TextBlock extends GraphObject { /** * Constructs a {@link TextBlock}, which by default has no string to show; if it did, * it would draw the text, wrapping if needed, in the default font using a black stroke. * * Typical usage: * * ```js * new go.TextBlock("Hello World", { font: "12px sans-serif", stroke: "gray" }) * ``` * * It is common to data-bind the {@link text}: * * ```js * // A Node used as the node template, holding a single TextBlock * myDiagram.nodeTemplate = * new go.Node() * .add( * new go.TextBlock({ font: "12px sans-serif", stroke: "darkgray" }) * .bind("text") * ); * * // It could be used with model data like this: * myDiagram.model = new go.GraphLinksModel( * [ * { key: "1", text: "First TextBlock" }, * { key: "2", text: "Second TextBlock" } * ]); * ``` * * @param text - The textblock's text. * @param init - Optional initialization properties. */ constructor(text?: string, init?: Partial); /** * A newly constructed {@link TextBlock} has no string to show; if it did, * it would draw the text, wrapping if needed, in the default font using a black stroke. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * (undocumented) * This static function gets the current ellipsis character or string for * TextBlocks that have {@link TextBlock.overflow} set to {@link TextOverflow.Ellipsis}. */ static getEllipsis(): string; /** * (undocumented) * This static function sets the ellipsis character or string for all * TextBlocks that have {@link TextBlock.overflow} set to {@link TextOverflow.Ellipsis}. * * The default is `"..."`, which works with all fonts. * * Note when using the ellipsis character, "…", you will need to specify a compatible * character set for your page, like UTF-8. * * Modifying the ellipsis character does not cause any TextBlocks to be remeasured or redrawn. * @param val */ static setEllipsis(val: string): void; /** * Gets the function that, given the TextBlock and numerical text height, computes the position to draw the baseline of a line of text in all TextBlocks. * By default this is null and default behavior returns `(textHeight * 0.75)`. * * This computation affects drawing only, and does not change TextBlock measurement calculations. * @since 2.0 */ static getBaseline(): ((textBlock: TextBlock, textHeight: number) => number) | null; /** * Sets the function that, given the TextBlock and numerical text height, computes the position to draw the baseline of a line of text in all TextBlocks. * * This computation affects drawing only, and does not change TextBlock measurement calculations. * It is expected this method will be called before or during initialization of any Diagram. * Diagrams will not redraw when this method has been called, * and you should call `Diagram.redraw()` if you are calling this method outside of your initialization. * * @param value * @since 2.0 */ static setBaseline(value: ((textBlock: TextBlock, textHeight: number) => number) | null): void; /** * Gets the function that, given the TextBlock and numerical text height, computes the position to draw the underline of a line of text in all TextBlocks. * By default this is null and default behavior returns `(textHeight * 0.75)`. * * This computation affects drawing only, and does not change TextBlock measurement calculations. * @since 2.0 */ static getUnderline(): ((textBlock: TextBlock, textHeight: number) => number) | null; /** * Sets the function that, given the TextBlock and numerical text height, computes the position to draw the underline of a line of text in all TextBlocks. * * This computation affects drawing only, and does not change TextBlock measurement calculations. * It is expected this method will be called before or during initialization of any Diagram. * Diagrams will not redraw when this method has been called, * and you should call `Diagram.redraw()` if you are calling this method outside of your initialization. * * @param value * @since 2.0 */ static setUnderline(value: ((textBlock: TextBlock, textHeight: number) => number) | null): void; /** * @deprecated See {@link Wrap.None}. */ static readonly None = Wrap.None; /** * @deprecated See {@link Wrap.Fit}. */ static readonly WrapFit = Wrap.Fit; /** * @deprecated See {@link Wrap.DesiredSize}. */ static readonly WrapDesiredSize = Wrap.DesiredSize; /** * @deprecated See {@link Wrap.BreakAll}. */ static readonly WrapBreakAll = Wrap.BreakAll; /** * @deprecated See {@link TextOverflow.Clip}. */ static readonly OverflowClip = TextOverflow.Clip; /** * @deprecated See {@link TextOverflow.Ellipsis}. */ static readonly OverflowEllipsis = TextOverflow.Ellipsis; /** * @deprecated See {@link TextFormat.Trim}. */ static readonly FormatTrim = TextFormat.Trim; /** * @deprecated See {@link TextFormat.None}. */ static readonly FormatNone = TextFormat.None; /** * Gets or sets the current font settings. * The font property must be a valid CSS string describing a font. * The font string can accept several CSS properties but they must be * in a specific order in order to render correctly across all browsers: * * `"font-style font-variant font-weight font-size font-family"` * * For example, `"Italic small-caps bold 32px Georgia, Serif"` is a valid font string * using every CSS font property. Not every browser can render every font option. * For more information about CSS font syntax, see CSS fonts (mozilla.org). * * If your Node sizes depend on TextBlocks, it is best to ensure any custom fonts you are using are finished loading before you load your Diagram. * This will ensure nodes are sized appropriately for the initial Diagram layout. * * The default font is "13px sans-serif". */ get font(): string; set font(value: string); /** * This static predicate returns true if the given font is a valid font. * @param font * @since 3.0 */ static isValidFont(font: string): boolean; /** * Gets or sets the TextBlock's text string. The default is an empty string. * The text of a TextBlock, along with the values of {@link font}, {@link wrap}, * {@link isMultiline} and sizing restrictions are what naturally determine * the size of the TextBlock. * * The text in textblocks can include manual line-breaks by using the character escape, `\n`. * * Leading and trailing whitespace is eliminated in each line of TextBlock text. * * If {@link editable} is set to true, users can edit textblocks with the {@link TextEditingTool}. */ get text(): string; set text(value: string); /** * Gets or sets the alignment location in the TextBlock's given space. * The only possible values are `"start"`, `"end"`, `"left"`, `"right"`, and `"center"`. * Any other value is invalid. * * This property is most pertinent when the TextBlock has multiple lines of text, * or when the TextBlock is given a size that differs from the text's natural size (such as with {@link desiredSize}). * * In left-to-right writing systems, `"start"` and `"left"` are synonymous, as are `"end"` and `"right"`. * * The default is `"start"`. * @see {@link verticalAlignment} */ get textAlign(): ('start' | 'end' | 'left' | 'right' | 'center'); set textAlign(value: ('start' | 'end' | 'left' | 'right' | 'center')); /** * Gets or sets how the TextBlock is displayed: Either normally or with a Horizontal or Vertical flip or both. * * Possible values are {@link Flip.None}, {@link Flip.Horizontal}, {@link Flip.Vertical}, or {@link Flip.Both}. * The default is {@link Flip.None}. * @since 2.0 */ get flip(): Flip; set flip(value: Flip); /** * Gets or sets the vertical alignment {@link Spot} of this TextBlock, used when * the TextBlock has more available vertical space than it needs to draw all lines. * * The default value is {@link Spot.Top}, which aligns the TextBlock to the top of its available space. * * The {@link textAlign} is often used along with this property to specify * where the should be positioned in its available space. * * This does not affect TextBlock coordinates or bounds, it only affects where text is drawn within the given area. * @see {@link textAlign} */ get verticalAlignment(): Spot; set verticalAlignment(value: Spot); /** * This read-only property returns the natural bounds of this TextBlock in local coordinates, * as determined by its {@link font} and {@link text} string, and optionally its {@link desiredSize}. */ get naturalBounds(): Rect; /** * Gets or sets whether or not the text displays multiple lines or embedded newlines. * If this is false, all characters including and after the first newline will be omitted. * The default is true. * @see {@link maxLines} */ get isMultiline(): boolean; set isMultiline(value: boolean); /** * Gets or sets whether or not the text is underlined. * The default is false. * @see {@link isStrikethrough} */ get isUnderline(): boolean; set isUnderline(value: boolean); /** * Gets or sets whether or not the text has a strikethrough line (line-through). * The default is false. * @see {@link isUnderline} */ get isStrikethrough(): boolean; set isStrikethrough(value: boolean); /** * Gets or sets whether the text should be wrapped if it is too long to fit on one line. * * Possible values are {@link Wrap.DesiredSize}, {@link Wrap.Fit}, {@link Wrap.BreakAll}, * and {@link Wrap.None}. * * The default value is {@link Wrap.DesiredSize}. * @see {@link overflow} */ get wrap(): Wrap; set wrap(value: Wrap); /** * Gets or sets how text that is too long to display should be handled. * * Possible values are {@link TextOverflow.Clip} and {@link TextOverflow.Ellipsis}. * For Ellipsis to work, you must constrain the available size of the TextBlock in some way, * such as setting {@link wrap} to {@link Wrap.None}, * or limiting the number of lines with {@link maxLines} or a height constraint. * * With Ellipsis, setting the {@link wrap} value to {@link Wrap.BreakAll} will allow ellipses to break partial words. * * The default value is {@link TextOverflow.Clip}. * @see {@link wrap} */ get overflow(): TextOverflow; set overflow(value: TextOverflow); /** * Gets whether the TextBlock text is truncated (overflowed) or not. * This value is set during a TextBlock's measurement. * * As with all read-only properties, using this property as a binding source is unlikely to be useful. * @since 2.3 * @see {@link overflow} */ get isOverflowed(): boolean; /** * Gets or sets the {@link Brush} or string that describes the stroke (color) of the text that is drawn. * * The default value is `"black"`. * Any valid CSS string can specify a solid color, and the {@link Brush} * class can be used to specify a gradient or pattern. * More information about the syntax of CSS color strings is available at: * CSS colors (mozilla.org). */ get stroke(): BrushLike; set stroke(value: BrushLike); /** * This read-only property returns the computed number of lines in this TextBlock, including lines created * from embedded newlines (`\n`), {@link wrap}ping, and {@link maxLines}. * * This value may be meaningless before the TextBlock is measured. * @see {@link lineHeight} */ get lineCount(): number; /** * This read-only property returns the height of a line of text in this TextBlock, not including any {@link spacingAbove} or {@link spacingBelow}. * * This value may be meaningless before the TextBlock is measured. * @since 2.2 * @see {@link lineCount} */ get lineHeight(): number; /** * Gets or sets whether or not this TextBlock allows in-place editing of the {@link text} * string by the user with the help of the {@link TextEditingTool}. * The default is false. * * See also {@link Part.textEditable}. */ get editable(): boolean; set editable(value: boolean); /** * Gets or sets the HTMLInfo that this TextBlock uses as its text editor in the TextEditingTool. * If null, the TextBlock will use the default text editor of the {@link TextEditingTool}. * The default is null. * The value should be set to an instance of {@link HTMLInfo}. * Setting this property might not affect any ongoing text editing operation. * * For example usage, see the Custom TextEditingTool Sample. */ get textEditor(): HTMLInfo | null; set textEditor(value: HTMLInfo | null); /** * Gets or sets the function to call if a text edit made with the {@link TextEditingTool} is invalid. * The default is null. */ get errorFunction(): ((tool: TextEditingTool, oldString: string, newString: string) => void) | null; set errorFunction(value: ((tool: TextEditingTool, oldString: string, newString: string) => void) | null); /** * Gets or sets how frequently this text should be drawn within a "Graduated" {@link Panel}, * in multiples of the {@link Panel.graduatedTickUnit}. * The default is 1. Any new value must be a positive integer. */ get interval(): number; set interval(value: number); /** * Gets or sets the fractional distance along the main shape of a "Graduated" {@link Panel} at which this text should start. * The default is 0; the value should range from 0 to 1. */ get graduatedStart(): number; set graduatedStart(value: number); /** * Gets or sets the fractional distance along the main shape of a "Graduated" {@link Panel} at which this kind of tick text should end. * The default is 1; the value should range from 0 to 1. */ get graduatedEnd(): number; set graduatedEnd(value: number); /** * Gets or sets the function to convert from a value along a "Graduated" {@link Panel} to a string. * The default returns a string representing the value rounded to at most 2 decimals. * * The function takes a number argument, a value between {@link Panel.graduatedMin} and {@link Panel.graduatedMax}, * and this TextBlock. * The function will return a string, the text that will appear at the value of the argument. * * Note that the second argument is the TextBlock, *not* a particular label that would be rendered at the given value. * The function, if supplied, must not have any side-effects. */ get graduatedFunction(): ((val: number, tb: TextBlock) => string) | null; set graduatedFunction(value: ((val: number, tb: TextBlock) => string) | null); /** * Gets or sets the function to determine which values along a "Graduated" {@link Panel} will be skipped. * The default is null and doesn't skip any text labels. * * The function takes a number argument, a value between {@link Panel.graduatedMin} and {@link Panel.graduatedMax}, * and this TextBlock. * The function will return a boolean, whether the text label will be skipped at the value of the argument. * * Note that the second argument is the TextBlock, *not* a particular label that would be rendered at the given value. * The function, if supplied, must not have any side-effects. * @since 2.0 */ get graduatedSkip(): ((val: number, tb: TextBlock) => boolean) | null; set graduatedSkip(value: ((val: number, tb: TextBlock) => boolean) | null); /** * Gets or sets the predicate that determines whether or not a user-edited string of text is valid. * If this is non-null, the predicate is called in addition to any {@link TextEditingTool.textValidation} predicate. * See {@link TextEditingTool.isValidText} for more details. * * ```js * function(textBlock, oldString, newString) * ``` * * The default predicate is null, which is equivalent to simply returning true. * * The function, if supplied, must not have any side-effects, and must return true or false. * @see {@link TextEditingTool.textValidation} */ get textValidation(): ((thisTextBlock: TextBlock, oldString: string, newString: string) => boolean) | null; set textValidation(value: ((thisTextBlock: TextBlock, oldString: string, newString: string) => boolean) | null); /** * Gets or sets the function that is called after the TextBlock's text has been edited by the {@link TextEditingTool}. * - The first argument is a reference to this TextBlock. * - The second argument is the previous text, before editing. * - The third argument is the current text, which is also TextBlock.text. * * ```js * function(textBlock, previousText, currentText) * ``` * * The default value is null -- no function is called. */ get textEdited(): ((thisTextBlock: TextBlock, oldString: string, newString: string) => void) | null; set textEdited(value: ((thisTextBlock: TextBlock, oldString: string, newString: string) => void) | null); /** * Gets or sets additional spacing above each line of text. * The default is zero. The value may be negative. * * This can be useful when you need to adjust the font spacing on * custom fonts or monospace fonts to suit your needs. * * @since 2.2 */ get spacingAbove(): number; set spacingAbove(value: number); /** * Gets or sets additional spacing below each line of text. * The default is zero. The value may be negative. * * This can be useful when you need to adjust the font spacing on * custom fonts or monospace fonts to suit your needs. * * @since 2.2 */ get spacingBelow(): number; set spacingBelow(value: number); /** * Gets or sets the policy for trimming whitespace on each line of text. * * Possible values are {@link TextFormat.Trim}, which trims whitespace before and after every line of text, * or {@link TextFormat.None}, which will not trim any whitespace and may be useful for preformatted text. * The default is {@link TextFormat.Trim}. * @since 2.2 */ get formatting(): TextFormat; set formatting(value: TextFormat); /** * Gets or sets the maximum number of lines that this TextBlock can display. * Value must be a greater than zero whole number or `Infinity`. * The default is `Infinity`. * * Modifying this value may modify the computed height of the TextBlock. * If maxLines is set, the value of {@link lineCount} will never be larger than maxLines. * @see {@link isMultiline} */ get maxLines(): number; set maxLines(value: number); /** * Gets or sets the an array of possible choices for a custom {@link TextEditingTool}. * The value must be an array of strings. * * The default value is null. * For example usage, see the Custom TextEditingTool Sample. */ get choices(): Array | null; set choices(value: Array | null); } /** * This enumeration specifies possible values for {@link Picture.imageStretch}. * @since 3.0 */ export declare enum ImageStretch { /** * Do not scale the image; there may be clipping in one or both directions if the available dimensions are too small. */ None = 0, /** * Scale the image in both directions so as to fit exactly in the given bounds; there is no clipping, but the aspect ratio may change, causing the image to appear stretched. */ Fill = 2, /** * Scale the image equally in both directions to fit the larger side of the image bounds. */ Uniform = 6, /** * Scale the image equally in both directions to fit the arranged (actual) bounds. There may be clipping in one dimension. */ UniformToFill = 7 } /** * A Picture is a {@link GraphObject} that shows an image, video-frame, or Canvas element. * * You can specify what to show by either setting the {@link source} URL property * to a URL string or the {@link element} property to an HTMLImageElement, * HTMLCanvasElement, or HTMLVideoElement. * * If a {@link source} URL is set, the Picture will automatically create a corresponding * HTMLImageElement and retain a reference to it in memory. If multiple Pictures specify * the same {@link source} URL then they will all refer to the same HTMLImageElement. * * An example Picture, within a Node template: * ```js * // A picture with the source set to "example.png". It will show a gray area until the image is loaded: * new go.Picture("example.png", { background: "gray", width: 50, height: 50 }) * ``` * * If an element is not completely loaded during Diagram initialization, a redraw may occur, * and if an image's size is not known before loading, the containing Part of this Picture * may be resized, causing side effects such as layouts. * This can be avoided by knowing the size of the image beforehand, * and setting the Picture's {@link GraphObject.desiredSize}. * * With some images (notably sprite sheets) only a portion of the image is expected to be drawn. * The {@link sourceRect} property allows the programmer to specify a rectangular area of * the source image that the Picture should display. * * The {@link imageStretch} property allows an image to be resized inside of its bounding box. * This property does not change the size of the Picture element, it only resizes or re-scales * the image to fit (or not) in its bounds. *

* For examples of sizing and {@link imageStretch}, * see the Introduction page on Pictures. * * The {@link errorFunction} property allows one to set a function to call when a source fails to load. * This is useful in instances where images cannot be guaranteed to work, such as with * user specified input. The error function can set the {@link source} to a known good value, * but care should be taken to avoid error infinite loops when doing so. */ export class Picture extends GraphObject { /** * The constructor creates a Picture that shows nothing until the * {@link source} or {@link element} is specified. It is also common to specify the * {@link GraphObject.desiredSize} to make sure that the picture's size is known * before the image is loaded asynchronously, so that layouts do not need to be recomputed. * * Common usage: * ```js * new go.Picture("example_image_url.png", { * width: 100, * height: 50 * }) * ``` * * Or: * * ```js * // specify a different source for each node in the node data * new go.Picture({ * width: 100, * height: 50 * }).bind("source") * ``` * * @param source - Optionally set the Pictures's {@link source}. * @param init - Optional properties to initialize. */ constructor(source?: string, init?: Partial); /** * The constructor creates a Picture that shows nothing until the * {@link source} or {@link element} is specified. It is also common to specify the * {@link GraphObject.desiredSize} to make sure that the picture's size is known * before the image is loaded asynchronously, so that layouts do not need to be recomputed. * @param init - Optional properties to initialize. */ constructor(init?: Partial); /** * (undocumented) * This static function clears the cache of loaded images, or removes the cached image for a particular URL. * * When an image is loaded by GoJS when specifying a Picture.source URL, * GoJS creates an Image element using that source and caches it. * That way, when many Picture elements refer to the same source, * they can refer to the same single object in memory. * @param url - optional, clear only a specified URL from the image cache. If relative urls are used as Picture sources, this must be in the same format. */ static clearCache(url?: string): void; /** * Gets or sets the Picture's HTML element that provides some kind of visual image. * * The default value is null. * This can be a HTMLImageElement, HTMLVideoElement, or HTMLCanvasElement. * If an image, this element must have its source (src) attribute defined. * Setting this does not set the {@link Picture.source} attribute and that attribute may be unknowable. * * If this property is set to an HTMLImageElement, and that element is not yet loaded before it is used, * the Diagrams using that Element will not redraw on their own. * You must call {@link redraw} after the image is finished loading if you wish for the Diagram to be updated immediately. */ get element(): HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | null; set element(value: HTMLImageElement | HTMLVideoElement | HTMLCanvasElement | null); /** * Gets or sets the Picture's source URL, which can be any valid image (png, jpg, gif, etc) URL. * * The default value is the empty string, which specifies no image source. * Setting this attribute creates an HTMLImageElement and sets the {@link Picture.element} * attribute to that element. When the element loads, this Picture may remeasure if no {@link GraphObject.desiredSize} was set, * and Diagrams using the picture will redraw. * * To avoid remeasuring and rearranging Parts as images load asynchronously, * be sure to set the {@link GraphObject.desiredSize} * (or {@link GraphObject.width} and {@link GraphObject.height}) to fixed values. * * Setting the source of multiple Pictures to the same URL will cause only one HTMLImageElement * to be created and shared. Setting the source to the empty string will set {@link Picture.element} to null. * It is commonplace to either specify a constant URL or to data bind this property to some data property, * perhaps using a conversion function in order to produce a proper URL. * * For cross-browser support of SVG sources additional care is needed. * See the final section of the Introduction page on Pictures. */ get source(): string; set source(value: string); /** * Attempts to reload a {@link Picture.source} image. This can be useful if the content on a server has changed, or was missing before. * If a new image is loaded, this Picture may remeasure and/or redraw. * * Because of browsers caching assets, you may additionally need to force a re-fetch of the Picture's source URL * with a `fetch` call such as: * * ```js * fetch(thisPicture.source, { cache: 'reload', mode: 'no-cors' }); * ``` * * This should normally be called within a transaction. * @since 2.1 */ reloadSource(): void; /** * Redraws a Picture, which can be useful if the backing {@link element} is an HTML Canvas or HTML Video that has changed. * This will not attempt to *reload* any image. If you need to do that, call {@link reloadSource}. * * This does not need to be called within a transaction, and will not re-measure anything. * @since 2.1 */ redraw(): void; /** * Gets or sets a function that returns a value for image.crossOrigin. * * The default value is null, which will not set a value for image.crossOrigin. * Set this property to a function that returns "anonymous" or "use-credentials" * if you want images to complete a cross-origin request. * Example: * ```js * new go.Picture({ * width: 64, * height: 64, * sourceCrossOrigin: pict => 'anonymous' * }) * .bind('source', 'path') * ``` */ get sourceCrossOrigin(): ((a: Picture) => string) | null; set sourceCrossOrigin(value: ((a: Picture) => string) | null); /** * Gets or sets the rectangular area of the source image that this picture should display. * This is only common with sprite maps and image tables. * * The value must be of type {@link Rect}. * The default value is Rect(NaN, NaN, NaN, NaN), which means the whole source image should be used. */ get sourceRect(): Rect; set sourceRect(value: Rect); /** * Gets or sets how the Picture's image is stretched within its bounding box. * Some images will be a different aspect ratio than their given size or {@link desiredSize}. * This property will never change the size of the Picture itself, * only the size of the image that is drawn in the Picture's {@link actualBounds}. * * Possible values are {@link ImageStretch.Fill}, {@link ImageStretch.Uniform}, * {@link ImageStretch.UniformToFill}, and {@link ImageStretch.None}. * The default is {@link ImageStretch.Fill}. * @see {@link imageAlignment} */ get imageStretch(): ImageStretch; set imageStretch(value: ImageStretch); /** * Gets or sets how the Picture is displayed: Either normally or with a Horizontal or Vertical flip or both. * * Possible values are {@link Flip.None}, {@link Flip.Horizontal}, {@link Flip.Vertical}, or {@link Flip.Both}. * The default is {@link Flip.None}. * @since 2.0 */ get flip(): Flip; set flip(value: Flip); /** * Gets or sets the Spot to align the source image to, when the source image * is smaller than the Picture. This is only relevant when * the {@link imageStretch} property value is not go.ImageStretch.Fill. * * This does not affect Picture coordinates or bounds, it only affects what is drawn within the given area. * The default value is {@link Spot.Center}. * @see {@link imageStretch} */ get imageAlignment(): Spot; set imageAlignment(value: Spot); /** * Gets or sets the function to call if an image set by {@link source} fails to load. * The arguments to this function are this Picture and the HTMLImageElement's "error" Event. * * This is called once per Picture, for every Picture that is using the same {@link source} that failed to load. * This will never be called if the {@link source} is never set, and is not called with Pictures that use {@link element} instead. * * The default value is null, meaning that no specific action occurs when there is an error loading an image. * @see {@link successFunction} */ get errorFunction(): ((a: Picture, b: Event) => void) | null; set errorFunction(value: ((a: Picture, b: Event) => void) | null); /** * Gets or sets the function to call when an image set by {@link source} loads successfully. * The arguments to this function are this Picture and the HTMLImageElement's "load" Event. * * This is called once per Picture, for every Picture that is using the same {@link source} that loaded successfully. * This will never be called if the {@link source} is never set, and is not called with Pictures that use {@link element} instead. * It is even called for a Picture source that has already loaded, so that creating copies of a Picture with this property set will * call it once for each newly created Picture. * * The default value is null, meaning that no specific action occurs when an image finishes loading. * @see {@link errorFunction} */ get successFunction(): ((a: Picture, b: Event) => void) | null; set successFunction(value: ((a: Picture, b: Event) => void) | null); /** * This read-only property returns the natural size of this picture as determined by its source's width and height. * The value is initially NaN x NaN until the picture has been measured. * It will use the {@link element}'s `naturalWidth` and `naturalHeight` if available. */ get naturalBounds(): Rect; } /** * This enumeration specifies possible values for {@link Part.layoutConditions}. These values can be combined as flags. * @since 3.0 */ export declare enum LayoutConditions { /** * Indicates that no operation on a Part causes invalidation of the {@link Layout} responsible for that Part. */ None = 0, /** * Indicates that when a Part is added to a Diagram or Group, it invalidates the {@link Layout} responsible for the Part. */ Added = 1, /** * Indicates that when a Part is removed from a Diagram or Group, it invalidates the {@link Layout} responsible for the Part. */ Removed = 2, /** * Indicates that when a Part's {@link GraphObject.visible} becomes true, it invalidates the {@link Layout} responsible for the Part. */ Shown = 4, /** * Indicates that when a Part's {@link GraphObject.visible} becomes false, it invalidates the {@link Layout} responsible for the Part. */ Hidden = 8, /** * Indicates that when a Node or simple Part's {@link GraphObject.actualBounds} changes size, * it invalidates the {@link Layout} responsible for the Part; * this flag is ignored for Parts that are Links. */ NodeSized = 16, /** * Indicates that when a {@link Group} has been laid out, it invalidates the {@link Layout} responsible for that Group; * this flag is ignored for Parts that are not Groups. */ GroupLayout = 32, /** * Indicates that when a Node or simple Part's {@link Part.category|category} changes, it invalidates the {@link Layout} responsible for the Part; * this flag is ignored for Parts that are Links. */ NodeReplaced = 64, /** * This is the default value for the {@link Part.layoutConditions} property, basically a combination of all of the conditions: * the {@link Layout} responsible for the Part is invalidated when the Part is added or removed or replaced * from the Diagram or Group, or when it changes visibility or size, or when a Group's layout has been performed. */ Standard = 127 } /** * This is the base class for all user-manipulated top-level objects. * Because it inherits from {@link Panel}, it is automatically a visual container * of other {@link GraphObject}s. * Because it thus also inherits from {@link GraphObject}, it also has properties such as * {@link GraphObject.actualBounds}, {@link GraphObject.contextMenu}, and {@link GraphObject.visible}. * * If you just want an object that users can select and manipulate, * you can create an instance of this class. * * If you want an object that also supports being connected by links to other objects, * use the {@link Node} class, which inherits from Part. * Create those connections by using instances of the {@link Link} class. * * If you want a node that logically contains a subgraph of nodes and links, * use the {@link Group} class, which inherits from {@link Node}. * * If you want an object that decorates another Part, without having to modify that Part, * use the {@link Adornment} class. * Adornments do not support linking or grouping or being selected. * * You can construct a Part, add {@link GraphObject}s to it programmatically, * and then add the part to a diagram by calling {@link Diagram.add}. * However it is commonplace to add data to a model by setting its {@link Model.nodeDataArray} or calling {@link Model.addNodeData}, * or for {@link Link}s, setting the {@link GraphLinksModel.linkDataArray} or calling {@link GraphLinksModel.addLinkData}. * Such actions will cause a diagram that is displaying the model to copy a template, * which is a Part that may have data {@link Binding}s, and add the new part to the diagram. * The {@link Panel.data} property will refer to that data object in the model. * * Some examples of adding Parts to a Diagram: * ```js * // A simple Part template * myDiagram.nodeTemplate = * new go.Part("Horizontal") * .add( * new go.Shape("Circle", { width: 20, height: 20 }), * new go.TextBlock("Hello World") * ); * // Node templates can be either Nodes, or simple Parts * // (But not Groups, Adornments, or Links) * * // Adds copies of the nodeTemplate bound to the specified node data: * myDiagram.model.nodeDataArray = * [ * { key: "Alpha" }, * { key: "Beta" } * ]; * * // Adds one copy of the nodeTemplate bound to the given node data: * myDiagram.model.addNodeData( { key: "Gamma" } ); * ``` *

* See the Introduction on using Models * for examples and more information. *

Layers and Z-ordering

* * Parts added to a Diagram exist in one of the Diagram's {@link Layer}s. * You can specify which layer the part should be in by setting {@link layerName}. * Parts cannot be nested in the visual tree -- they cannot be added to other Parts of Panels. * * Parts can be individually z-ordered within a layer by setting {@link zOrder}. * Parts within the same layer that have a higher zOrder number will be drawn above parts with a lower number. *

Size and Position

* * The size and position of a part are given by its {@link GraphObject.actualBounds}. * The size is determined by the {@link GraphObject}s that are elements inside this part. * You can change the position by setting {@link GraphObject.position} or {@link Part.location}. * * The "location" of a part is commonly the same as its "position". * The "position" is always the point that is at the top-left corner of the area occupied by the part. * But the "location" may be different from the "position" if you want to think of the part as being "at" a different spot in the part. * For example, you might want the "location" to be at the center of a {@link Picture} that has a {@link TextBlock} title of arbitrary size. * In this case you would set the {@link locationSpot} to be {@link Spot.Center} and the {@link locationObjectName} * to be the name of the Picture element in your Part. * * A part may be selected or de-selected by setting its {@link isSelected} property. * This may also happen due to a call to {@link Diagram.select} or other operations that change the selection. * The user may change this property as part of the operation of the {@link ClickSelectingTool}, * due to the user's mouse click, if the part is {@link selectable}. *

Ability Properties (Permissions)

* * There are many properties named "...able", that control what operations the user may perform on this part. * These properties correspond to the similarly named properties on {@link Diagram} and {@link Layer} that govern the * behavior for all parts in all layers or for all parts in the given layer. * For example, the {@link Part.copyable} property corresponds to the properties {@link Diagram.allowCopy} and {@link Layer.allowCopy}. * * For each of these "ability" properties there is a corresponding "can..." predicate. * For example, the {@link Part.canCopy} predicate is false if any of the three previously named properties is false. * Commands and tools will normally call these predicates rather than just looking at Part properties. *

* For more discussion about permissions, please read: Permissions. * * As previously mentioned, each {@link Diagram} supports the notion of selected parts. * One way of displaying that a part is selected is by modifying the part. * You can set the {@link selectionChanged} property to be a function that is called when the value of {@link isSelected} has changed; * it is passed the Part as the first argument. * The function can modify the color of one or more {@link GraphObject}s in the visual tree of that Part. * Or perhaps it could toggle the {@link GraphObject.visible} property of an object that is normally hidden when the part is not selected. * * The Part class also supports showing separate visual objects for a part when it gets selected. * These visuals are typically used to show that the part is selected ("selection handles") * or are used to allow the user to manipulate or modify the part with a tool ("tool handles"). * These handles are instances of {@link Adornment}s. * The {@link updateAdornments} method is responsible for showing or hiding adornments, * normally depending on whether the part is selected. * * When the {@link selectionAdorned} property is true, a selected part automatically gets an {@link Adornment} created for it. * By default the selection adornment is just a simple blue box around the Part, and a blue shape following the route of a selected Link. * However you can set the {@link selectionAdornmentTemplate} to an arbitrarily complex Adornment. * This way it can show more information or buttons for executing various commands when the user selects a Part. * * Tool handles are shown for those mode-less mouse-down tools that need it. * The process of updating adornments for a part will call {@link Tool.updateAdornments} on each tool in {@link ToolManager.mouseDownTools}. * Most tools might not need special tool handles. * But, for example, {@link ResizingTool} naturally will want to create an adornment with eight resize handles * positioned at the corners and at the middles of the sides of the selected node's visual element, * if the node has its {@link canResize} function returning true. * * One may not always want the whole Part to get the selection handle or all tool handles. * Sometimes one wants to emphasize selection by highlighting a particular element within the part's visual tree. * This can be achieved by setting the {@link selectionObjectName} property, * and making sure the desired element has the same {@link GraphObject.name} property value. *

* For more discussion about selection, see Selection. * * Similarly the {@link resizeObjectName} and {@link rotateObjectName} properties direct the * corresponding {@link ResizingTool} and {@link RotatingTool} to operate on the particular {@link GraphObject} * in the Part's visual tree with the given name. * That includes both providing tool handles and actually modifying properties on that object. * * Parts are not resizable or rotatable by default: you need to set {@link resizable} and/or {@link rotatable} to true. *

* For more discussion about tools, see Tools. * * A Part may be positioned (or a {@link Link} may be routed) by a {@link Layout}. * This will happen automatically if {@link Diagram.layout} or {@link Group.layout} are set. * The default {@link Diagram.layout} will position any nodes that were not given explicit positions or location. * * If you set {@link isLayoutPositioned} to false, this part will not participate in any of the standard layouts, * so it will not be moved by a layout or affect other parts in a layout. * In order for the part to get a {@link location} or position you will need to supply it explicitly. * * As parts are added to or removed from a diagram, the {@link Layout} responsible for positioning the part is invalidated. * This will cause the layout to be performed again in the near future, at the end of the transaction. * This automatic layout invalidation also occurs as parts change their visibility ({@link GraphObject.visible}) * or their size ({@link GraphObject.actualBounds}). * If you do want there to be a {@link Diagram.layout} but you do not want an automatic layout to happen * after removing parts (for example), you can set {@link layoutConditions} not to include the {@link LayoutConditions.Removed} flag. * In this particular case, you could set {@link layoutConditions} to: * `go.LayoutConditions.Standard & ~go.LayoutConditions.Removed`. * It may also reasonable for your application to set it to {@link LayoutConditions.None}. * Do not forget to consider applying the same conditions to links as well as to nodes and groups. * * If you want to save the locations/positions of the parts in a diagram, it is commonplace to * data bind the {@link location} to a property on your node data with a TwoWay {@link Binding} * (call {@link Binding.makeTwoWay}). For example: * ```js * new go.Part("Horizontal") * .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify) * // ... * ``` * * Then as the nodes are moved, whether manually by the user or automatically by a {@link Layout}, * the model data is automatically updated with the location. *

* For more discussion about related topics, see Selection, * Tools, and * Permissions. * * Parts that are templates should have no relationships with other Parts. * Only real Parts that are in a Diagram can belong to Groups or have any Adornments. * Only real Nodes in a Diagram can be connected with Links. */ export class Part extends Panel { /** * Constructs an empty Part of the given {@link type}. Default type is {@link Panel.Position}. * The panel type must be a {@link PanelLayout}, such as {@link Panel.Vertical}. * The string value such as "Auto" may also be used. * * Usage example: * *```js * // Constructs a Part, sets properties on it, * // adds a data binding to it, * // and adds two GraphObjects to the Part: * const p = new go.Part("Auto", { * margin: 5, * background: "red" * }) * .bind("location", "loc") * .add( * new go.Shape("RoundedRectangle"), * new go.TextBlock("Some Text") * ); * ``` * * @param type - a string or PanelLayout, such as "Horizontal" or {@link Panel.Vertical}. * If not supplied, the default Panel type is "Position". * @param init - Optional initialization properties. */ constructor(type?: PanelLayout | string, init?: Partial); /** * Constructs an empty Panel. Default type is {@link Panel.Position}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * @deprecated See {@link LayoutConditions.None}. */ static readonly LayoutNone = LayoutConditions.None; /** * @deprecated See {@link LayoutConditions.Added}. */ static readonly LayoutAdded = LayoutConditions.Added; /** * @deprecated See {@link LayoutConditions.Removed}. */ static readonly LayoutRemoved = LayoutConditions.Removed; /** * @deprecated See {@link LayoutConditions.Shown}. */ static readonly LayoutShown = LayoutConditions.Shown; /** * @deprecated See {@link LayoutConditions.Hidden}. */ static readonly LayoutHidden = LayoutConditions.Hidden; /** * @deprecated See {@link LayoutConditions.NodeSized}. */ static readonly LayoutNodeSized = LayoutConditions.NodeSized; /** * @deprecated See {@link LayoutConditions.GroupLayout}. */ static readonly LayoutGroupLayout = LayoutConditions.GroupLayout; /** * @deprecated See {@link LayoutConditions.NodeReplaced}. */ static readonly LayoutNodeReplaced = LayoutConditions.NodeReplaced; /** * @deprecated See {@link LayoutConditions.Standard}. */ static readonly LayoutStandard = LayoutConditions.Standard; /** * Re-evaluate all data bindings in this Part, * in order to assign new property values to the {@link GraphObject}s in this visual tree * based on this this object's {@link data} property values. * This method does nothing if {@link data} is null. * * It is better to call {@link Model.setDataProperty} to modify data properties, * because that will both record changes for undo/redo and will update all bindings * that make depend on that property. * * To update relationships between nodes, call {@link updateRelationshipsFromData}. * @param srcprop - An optional source data property name: * when provided, only evaluates those {@link Binding}s that use that particular property; * when not provided or when it is the empty string, all bindings are evaluated. * @see {@link updateRelationshipsFromData} */ updateTargetBindings(srcprop?: string): void; /** * Update all of the references to nodes in case they had been modified in the model without * properly notifying the model by calling {@link GraphLinksModel.setGroupKeyForNodeData} or * {@link GraphLinksModel.setToKeyForLinkData} or other similar methods. * This method does not conduct a transaction, so you need to start and commit one yourself. * * This only updates the relationships between nodes, to have them reflect what is now declared in the model data. * For example, in a GraphLinksModel if code has changed the value of the "to" property of a link data, * calling this method on the corresponding {@link Link} would cause the link to connect with * the {@link Node} whose data has the new key. * * To update {@link GraphObject} properties that are data bound, call {@link updateTargetBindings}. * @virtual * @see {@link updateTargetBindings} */ updateRelationshipsFromData(): void; /** * This read-only property returns the Part's Model data key if it is in a Diagram and is backed by Model data. * Otherwise this returns undefined. * @see {@link Model.getKeyForNodeData} */ get key(): Key; /** * This read-only property returns an iterator over all of the {@link Adornment}s associated with this part. * After each call to the iterator's next() method that returns true, * the iterator's key will be the category and the iterator's value will * be an {@link Adornment}. * * Templates should not have any adornments. */ get adornments(): Iterator; /** * Find an {@link Adornment} of a given category associated with this Part. * * Templates should not have any adornments. * @param category * @returns Returns null if no such Adornment was found. */ findAdornment(category: string): Adornment | null; /** * Associate an {@link Adornment} with this Part, perhaps replacing any existing adornment of the same category. * Don't forget to set {@link Adornment.adornedObject} before calling this method. * This adds the Adornment to the {@link Layer} named by {@link layerName}, normally "Adornment". * * Adornments are also data bound to the same data that this Part has, if any. * If the Adornment was already associated with a Part, it is unassociated with that old Part. * * This method should not be called on templates. * @param category - a string identifying the kind or role of the given adornment for this Part. * @param ad - the new Adornment. */ addAdornment(category: string, ad: Adornment | null): void; /** * Remove any {@link Adornment} of the given category that may be associated with this Part. * @param category - a string identifying the kind or role of the given adornment for this Part. */ removeAdornment(category: string): void; /** * Remove all adornments associated with this part. */ clearAdornments(): void; /** * This is responsible for creating any selection {@link Adornment} (if this Part {@link isSelected}) and * any tool adornments for this part. * @virtual */ updateAdornments(): void; /** * (undocumented) */ invalidateAdornments(): void; /** * This read-only property returns the {@link Layer} that this Part is in. * The value is the Layer that is named with the value of {@link layerName}. * If you want to change what Layer this Part is in, change the value of {@link layerName} to refer to a different Layer. * * This will be null if it has not yet been added to a {@link Diagram}, * or if it has already been removed from a Diagram. * @see {@link layerName} */ get layer(): Layer | null; /** * This read-only property returns the {@link Diagram} that this Part is in. * * This will be null if it is not in a {@link Layer}. */ get diagram(): Diagram | null; /** * Gets or sets the layer name for this part. * The initial value is an empty string, which is the name of the default layer. * The value of this property determines the value of {@link layer}. * * If this part is not yet in a {@link Diagram}, * this value is used by {@link Diagram.add} * to determine which {@link Layer} this part should go in. * If no layer can be found with this name, it uses the default layer. * * Changing the value of this property while it is already in a layer * causes it to change layers if needed. * @see {@link layerChanged} */ get layerName(): string; set layerName(value: string); /** * Gets or sets the function to execute when this part changes layers. * It is typically used to modify the appearance of the part. * This function must not change the layer of this part by setting {@link layerName}. * * If this property value is a function, it is called with three arguments, * this {@link Part}, the old {@link Layer} (may be null), and the new {@link Layer} (may be null). * By default this property is null -- no function is called. * @see {@link layerName} */ get layerChanged(): ((thisPart: Part, oldLayer: Layer | null, newLayer: Layer | null) => void) | null; set layerChanged(value: ((thisPart: Part, oldLayer: Layer | null, newLayer: Layer | null) => void) | null); /** * Gets or sets the Z-ordering position of this Part within its Layer. * * Within the same layer, nodes with larger zOrder values are placed in front of nodes with smaller zOrder values. * When the value is NaN the ordering is not specified. * The default value is NaN. * * When a {@link Group} has a zOrder value of NaN, it is automatically placed behind its member nodes and links * that also have no zOrder. * Such automatic ordering is not guaranteed if any nodes including the groups have a numeric zOrder. * If you do want to specify the zOrder of nodes, you should also specify the zOrder of their containing groups * unless those groups are in different layers. */ get zOrder(): number; set zOrder(value: number); /** * This read-only property returns the {@link GraphObject} that determines the location of this Part. * The value will be in the visual tree of this Part and is usually named with * the value of {@link locationObjectName}. * For Adornments and Groups, the locationObject will be the Placeholder, if it has a visible one. */ get locationObject(): GraphObject; /** * Gets or sets the minimum location of this Part to which the user may drag using the {@link DraggingTool}. * * Value must be of type {@link Point}. * The initial value is (-Infinity, -Infinity), which imposes no position constraint. * A X value of NaN causes {@link Diagram.computeMove} to use the part's current location's X value as the minimum, * and similarly for NaN as the Y value. * @see {@link location} * @see {@link maxLocation} * @see {@link dragComputation} * @see {@link movable} */ get minLocation(): Point; set minLocation(value: Point); /** * Gets or sets the maximum location of this Part to which the user may drag using the {@link DraggingTool}. * * Value must be of type {@link Point}. * The initial value is (Infinity, Infinity), which imposes no position constraint. * A X value of NaN causes {@link Diagram.computeMove} to use the part's current location's X value as the maximum, * and similarly for NaN as the Y value. * @see {@link location} * @see {@link minLocation} * @see {@link dragComputation} * @see {@link movable} */ get maxLocation(): Point; set maxLocation(value: Point); /** * Gets or sets the name of the {@link GraphObject} that provides the location of this Part. * This name determines the value of {@link locationObject}. * The actual {@link location} also depends on the {@link locationSpot}. * * The initial value is an empty string, meaning the whole Part itself determines the location. * If you want to use a particular GraphObject in the visual tree of this Part, * set this property to be the {@link GraphObject.name} of the element that you want to be the {@link locationObject}. * * For Groups and Adornments that have Placeholders, this property is ignored, * because the locations of those Groups and Adornments are determined by their Placeholders (if it has a visible one), * not by another element in their visual trees. * @see {@link location} * @see {@link locationSpot} */ get locationObjectName(): string; set locationObjectName(value: string); /** * Gets or sets the location Spot of this Node, the spot on the {@link locationObject} * that is used in positioning this part in the diagram. * * Value must be of the type {@link Spot}. * The initial value is `Spot.TopLeft`. * The value must be a specific spot -- i.e. one for which {@link Spot.isSpot} is true. * * It is commonplace to set this property to `Spot.Center`, so that the {@link location} * has a value corresponding to the point at the center of this Part's {@link locationObject} element. * But the {@link GraphObject.position} of a Part is always at the top-left corner * point of the {@link GraphObject.actualBounds}. * * Note that the locationSpot for Groups and Adornments that have visible Placeholders will always be * relative to the Placeholder, because they determine the location for the Group or Adornment * and {@link locationObjectName} is ignored in those cases. * @see {@link location} * @see {@link locationObjectName} */ get locationSpot(): Spot; set locationSpot(value: Spot); /** * Move this part and any parts that are owned by this part to a new position. * * If this part is a {@link Group}, it also moves all of its members, recursively. * If this part is a {@link Link}, it also moves all of its label nodes. * * This method does not perform a transaction or start any animation. * @virtual * @param newpos - a new {@link Point} in document coordinates. * @param useLocation - true if you want to set the {@link location} instead of the position. False by default. */ move(newpos: Point, useLocation?: boolean): void; /** * Move this part and any parts that are owned by this part to a new position. * This just calls {@link move} without the caller having to allocate a new {@link Point}. * @param newx - a new X value in document coordinates. * @param newy - a new Y value in document coordinates. * @param useLocation - true if you want to set the {@link location} instead of the position. False by default. */ moveTo(newx: number, newy: number, useLocation?: boolean): void; /** * This predicate is true if this Part can be seen. * Parts that can be seen can be manipulated by the user, can take space in the document, or can take part in a layout, * among many possibilities. * Note that the value of this predicate can often be false even while {@link GraphObject.visible} is true. * * A Part is not seen if it is not {@link GraphObject.visible} or if it is in a {@link Layer} that is not {@link Layer.visible}. * * If a Part is a member of a {@link Group} and the Group is not {@link Group.isSubGraphExpanded}, the part is not seen. * (The containing Group might still be visible.) * * If a {@link Node} is a "tree child" of a Node that is not {@link Node.isTreeExpanded}, the node is not seen. * (The parent Node might still be visible.) * * If a {@link Link} is connected to or from a {@link Node} that is not `isVisible()` * and is not a member of a {@link Group} that `isVisible()`, the link is not seen. * * If a {@link Node} is a "link label" of a {@link Link} and that Link is not `isVisible()`, the node is not seen. * * This is different from {@link GraphObject.isVisibleObject}, * which ignores whether the {@link Layer} is visible and just checks {@link GraphObject.visible} * up the chain of containing {@link Panel}s. * * If you want to know whether a Part is in the Diagram's viewport, try: * ```js * diagram.viewportBounds.containsRect(part.actualBounds); * ``` * * or: * ```js * diagram.viewportBounds.intersectsRect(part.actualBounds); * ``` * @virtual * @returns true if {@link GraphObject.visible} is true and if {@link Layer.visible} is true. */ isVisible(): boolean; /** * Returns the Rect in document coordinates for this object's bounds. * If this GraphObject is a Part, the rect will be identical to its {@link actualBounds}. * @param result - an optional Rect that is modified and returned. * @returns in document coordinates. * @see {@link getDocumentPoint} * @since 2.0 */ getDocumentBounds(result?: Rect): Rect; /** * Measures if needed to make sure the {@link GraphObject.measuredBounds} and {@link GraphObject.naturalBounds} are all real numbers, * primarily to get the actual width and height. * {@link GraphObject.actualBounds} will get a real width and height, but the x and y values may continue to be `NaN` * if they were that way beforehand. * * This is sometimes necessary to call when defining custom layouts or implementing virtualization, * so that it can work with the actual size of the nodes. * * For efficiency, do not call this method unnecessarily. * @see {@link Diagram.ensureBounds} */ ensureBounds(): void; /** * Gets or sets the position of this part in document coordinates, * based on the {@link locationSpot} in this part's {@link locationObject}. * * Value must be of type {@link Point}. * The initial value is Point(NaN, NaN). * It is commonplace to data bind this property to some property on your model node data. * * The value is related to the {@link GraphObject.position}. * For Parts, both are in document coordinates; setting one property will set the other property. * By default both will have the same value. * However, by setting either or both of {@link locationSpot} and {@link locationObjectName}, * the location will be determined by a spot in the {@link locationObject}, * a {@link GraphObject} that is in the visual tree of this Part. * The {@link GraphObject.position} will always refer to the point at the top-left corner of the whole part. * * The {@link minLocation} and {@link maxLocation} limit the location of a part, not its position. * Grid snapping will normally locate the location to be on grid points. * @see {@link locationObjectName} * @see {@link locationSpot} * @see {@link movable} * @see {@link maxLocation} * @see {@link minLocation} * @see {@link dragComputation} */ get location(): Point; set location(value: Point); /** * (undocumented) * @returns whether this Part has a visible Placeholder */ hasPlaceholder(): this is (Group | Adornment); /** * Gets or sets the category of this part, * typically used to distinguish different kinds of nodes or links. * * The initial value is an empty string, which is the default category. * Any new value must be a string. * This should not be set in templates. * * When building Parts for node data or link data in a model, * the {@link Diagram} will call {@link Model.getCategoryForNodeData} or * {@link GraphLinksModel.getCategoryForLinkData} to get the category string for the data object. * The diagram uses this value to look up a template in {@link Diagram.nodeTemplateMap}, * {@link Diagram.linkTemplateMap} or {@link Diagram.groupTemplateMap}. * That template is copied to create the actual Part that is added to the diagram. * The diagram will set this property to remember the category it used. * * Note that the class of the new Part must be the same as the class of the original Part. * For example, a Node cannot be replaced by a simple Part or vice-versa. * Nor can a Link be replaced by a subclass of Link or vice-versa. * * To change the category for a Part created for model data, call {@link Model.setCategoryForNodeData} or * {@link GraphLinksModel.setCategoryForLinkData}. * * This property is also used to distinguish {@link Adornment}s on a Part. * In this scenario you create the Adornment, often indirectly by specifying a template, * and set this property explicitly. * For example, {@link ResizingTool.updateAdornments} creates a resizing Adornment from the * {@link Part.resizeAdornmentTemplate} and sets its category to be "Resizing". * Changing the category of an existing Adornment will update any adorned part's association. */ get category(): string; set category(value: string); set self(clone: Part); /** * This predicate returns true if {@link copyable} is true, * if the layer's {@link Layer.allowCopy} is true, and * if the diagram's {@link Diagram.allowCopy} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may copy this part. */ canCopy(): boolean; /** * This predicate returns true if {@link deletable} is true, * if the layer's {@link Layer.allowDelete} is true, and * if the diagram's {@link Diagram.allowDelete} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may delete this part. */ canDelete(): boolean; /** * This predicate returns true if {@link textEditable} is true, * if the layer's {@link Layer.allowTextEdit} is true, and * if the diagram's {@link Diagram.allowTextEdit} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may edit this part. */ canEdit(): boolean; /** * This predicate returns true if {@link groupable} is true, * if the layer's {@link Layer.allowGroup} is true, and * if the diagram's {@link Diagram.allowGroup} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may group this part. */ canGroup(): boolean; /** * This predicate returns true if {@link movable} is true, * if the layer's {@link Layer.allowMove} is true, and * if the diagram's {@link Diagram.allowMove} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may move this part. */ canMove(): boolean; /** * This predicate returns true if {@link reshapable} is true, * if the layer's {@link Layer.allowReshape} is true, and * if the diagram's {@link Diagram.allowReshape} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may reshape this part. */ canReshape(): boolean; /** * This predicate returns true if {@link resizable} is true, * if the layer's {@link Layer.allowResize} is true, and * if the diagram's {@link Diagram.allowResize} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may resize this part. */ canResize(): boolean; /** * This predicate returns true if {@link rotatable} is true, * if the layer's {@link Layer.allowRotate} is true, and * if the diagram's {@link Diagram.allowRotate} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may rotate this part. */ canRotate(): boolean; /** * This predicate returns true if {@link selectable} is true, * if the layer's {@link Layer.allowSelect} is true, and * if the diagram's {@link Diagram.allowSelect} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may select this part. */ canSelect(): boolean; /** * Gets or sets whether the user may copy this part. * The initial value is true. * @see {@link canCopy} */ get copyable(): boolean; set copyable(value: boolean); /** * Gets or sets whether the user may delete this part. * The initial value is true. * @see {@link canDelete} */ get deletable(): boolean; set deletable(value: boolean); /** * Gets or sets whether the user may do in-place text editing on {@link TextBlock}s in this part * that have {@link TextBlock.editable} set to true. * The initial value is true. * @see {@link canEdit} * @see {@link TextBlock.editable} */ get textEditable(): boolean; set textEditable(value: boolean); /** * Gets or sets whether the user may group this part to be a member of a new {@link Group}. * The initial value is true. * * The grouping command is implemented by {@link CommandHandler.groupSelection} * and depends on {@link CommandHandler.archetypeGroupData} having been set to a node data object. * A Group can be ungrouped by the user if you set {@link Group.ungroupable} to true. * @see {@link canGroup} */ get groupable(): boolean; set groupable(value: boolean); /** * Gets or sets whether the user may move this part. * The initial value is true. * @see {@link canMove} * @see {@link dragComputation} * @see {@link maxLocation} * @see {@link minLocation} */ get movable(): boolean; set movable(value: boolean); /** * Gets or sets whether a selection adornment is shown for this part when it is selected. * The initial value is true. * @see {@link selectionChanged} * @see {@link selectionAdornmentTemplate} */ get selectionAdorned(): boolean; set selectionAdorned(value: boolean); /** * Gets or sets whether this Part is part of the document bounds. * * The initial value is true. * A value of false causes {@link Diagram.computeBounds} to ignore this part. * If the value is false, it is possible that user will not be able to scroll far enough to see this part, * if the part's {@link GraphObject.actualBounds} are outside of the {@link Diagram.documentBounds}. */ get isInDocumentBounds(): boolean; set isInDocumentBounds(value: boolean); /** * Gets or sets whether a {@link Layout} positions this Node or routes this Link. * This property affects the value of {@link canLayout}. * * The initial value is true, meaning that this part is laid out by the layout responsible for this Part. * If this part is a member of a {@link Group}, it is the {@link Group.layout}, * otherwise it is the {@link Diagram.layout}. * * A value of false means that this part is not affected by and does not affect any automatic layout, * so the {@link layoutConditions} property is ignored. * You will need to make sure that it has a real {@link location} or {@link GraphObject.position} value, * or else the Part might not be visible anywhere in the diagram. * * Another way of controlling when layouts are invalidated is by setting * {@link Part.layoutConditions} or {@link Layout.isInitial} or {@link Layout.isOngoing}. */ get isLayoutPositioned(): boolean; set isLayoutPositioned(value: boolean); /** * Gets or sets whether the user may select this part. * The initial value is true. * * If you set this to true you may also want to set {@link selectionObjectName} * to the {@link GraphObject.name}d element that you want to be adorned * when the Part is selected. * @see {@link canSelect} * @see {@link isSelected} * @see {@link selectionAdorned} * @see {@link selectionObjectName} * @see {@link selectionAdornmentTemplate} * @see {@link selectionChanged} */ get selectable(): boolean; set selectable(value: boolean); /** * Gets or sets whether the user may reshape this part. * The initial value is false. * @see {@link canReshape} * @see {@link LinkReshapingTool} */ get reshapable(): boolean; set reshapable(value: boolean); /** * Gets or sets whether the user may resize this part. * The initial value is false. * * If you set this to true you may also want to set {@link resizeObjectName} * to the {@link GraphObject.name}d element that you want the user to resize. * It is also commonplace to add a TwoWay {@link Binding} of that named element's * {@link GraphObject.desiredSize} in order to save to the model data the value that the user * set via the {@link ResizingTool}. * @see {@link canResize} * @see {@link resizeObjectName} * @see {@link resizeCellSize} * @see {@link resizeAdornmentTemplate} */ get resizable(): boolean; set resizable(value: boolean); /** * Gets or sets whether the user may rotate this part. * The initial value is false. * * If you set this to true you may also want to set {@link rotateObjectName} * to the {@link GraphObject.name}d element that you want the user to rotate. * It is also commonplace to add a TwoWay {@link Binding} of that named element's * {@link GraphObject.angle} in order to save to the model data the value that the user * set via the {@link RotatingTool}. * @see {@link canRotate} * @see {@link rotateObjectName} * @see {@link rotateAdornmentTemplate} */ get rotatable(): boolean; set rotatable(value: boolean); /** * Gets or sets whether this Part is selected. * The initial value is false. * * Selected parts typically are shown either with an {@link Adornment} * or with a different appearance by changing the brush or visibility of one or * more of the {@link GraphObject}s within the part. * * Changing this value does not by itself raise any "ChangingSelection" and "ChangedSelection" {@link DiagramEvent}s. * {@link Tool}s and the {@link CommandHandler} and methods such as {@link Diagram.select} do raise those DiagramEvents * because they want to surround changes to this property with a single "ChangingSelection" DiagramEvent beforehand and a single "ChangedSelection" afterwards. * @see {@link selectable} * @see {@link selectionAdorned} * @see {@link selectionChanged} * @see {@link selectionObjectName} * @see {@link selectionAdornmentTemplate} */ get isSelected(): boolean; set isSelected(value: boolean); /** * Gets or sets whether this Part is highlighted. * The initial value is false. * * Highlighted parts may be shown with a different appearance by changing the brush or visibility of one or * more of the {@link GraphObject}s within the part. * One way of doing that is by using binding. * Consider part of the definition of a Node template: * ```js * new go.Shape({ * // ... shape properties * }) * // Shape.fill is bound to Node.data.color * .bind("fill", "color") * // Shape.stroke is red when Node.isHighlighted is true, black otherwise * .bindObject("stroke", "isHighlighted", h => h ? "red" : "black") * ``` * @see {@link highlightedChanged} * @see {@link Diagram.highlighteds} * @see {@link Diagram.highlight} * @see {@link Diagram.highlightCollection} * @see {@link Diagram.clearHighlighteds} */ get isHighlighted(): boolean; set isHighlighted(value: boolean); /** * Gets or sets whether this part will draw shadows. * The initial value is false. * * By default, setting this property to true will attempt to draw shadows only * on the GraphObjects in this Part that appear to act as background objects, and * not on GraphObjects that appear to be in front of other GraphObjects in the Part. * * To finely control shadows, you may need to set {@link GraphObject.shadowVisible} on * elements of this Part, so that they explicitly do or do not get shadowed accordingly. * * The color of the shadow is determined by {@link shadowColor}. * The opacity of the shadow color is multiplied by the opacity of the shadowed object's brush. * So, for example, if you have a {@link Panel} with a {@link GraphObject.background} * that is "transparent", the shadow that is drawn for the panel will also be transparent. * * The direction of the shadow that is cast is controlled by {@link shadowOffset}, * and is independent of the {@link Diagram.scale}. * The sharpness of the shadow is controlled by {@link shadowBlur}. * @see {@link shadowOffset} * @see {@link shadowColor} * @see {@link shadowBlur} * @see {@link GraphObject.shadowVisible} */ get isShadowed(): boolean; set isShadowed(value: boolean); /** * Gets or sets whether this part may be animated. * The initial value is true. */ get isAnimated(): boolean; set isAnimated(value: boolean); /** * Gets or sets the function to execute when this {@link isHighlighted} changes. * It is typically used to modify the appearance of the part. * This function must not highlight or unhighlight any parts. * * If this property value is a function, it is called with one argument, * this {@link Part} that whose {@link isHighlighted} value changed. * By default this property is null. * @see {@link isHighlighted} */ get highlightedChanged(): ((thisPart: Part) => void) | null; set highlightedChanged(value: ((thisPart: Part) => void) | null); /** * Gets or sets the name of the {@link GraphObject} that should get a selection handle * when this part is selected. * The value of this property affects the value of {@link selectionObject}. * The initial value is an empty string, meaning the whole {@link Part} itself gets any selection handle. * * If no GraphObject has a {@link GraphObject.name} that is this name, {@link selectionObject} returns the whole Part. * @see {@link selectable} * @see {@link selectionObject} */ get selectionObjectName(): string; set selectionObjectName(value: string); /** * Gets or sets the {@link Adornment} template used to create a selection handle for this Part. * * If this is null, depending on the class of this Part, the value of {@link Diagram.nodeSelectionAdornmentTemplate}, {@link Diagram.groupSelectionAdornmentTemplate}, * or {@link Diagram.linkSelectionAdornmentTemplate} is used instead. * * It is commonplace to make use of a {@link Placeholder} in an {@link Adornment} for a {@link Node}, {@link Group}, or simple {@link Part}. * The Placeholder represents the {@link Adornment.adornedObject} of the adorned Part. * For {@link Link}s, the Adornment must be of {@link Panel.type} {@link Panel.Link}. * @see {@link selectable} * @see {@link selectionObjectName} */ get selectionAdornmentTemplate(): Adornment | null; set selectionAdornmentTemplate(value: Adornment | null); /** * This read-only property returns the {@link GraphObject} that should get a selection handle when this part is selected. * The value will be in the visual tree of this Part and is usually named with * the value of {@link selectionObjectName}. * When the {@link selectionObjectName} is unspecified, this whole Part is used as the "selection object". * @see {@link selectable} * @see {@link selectionObjectName} */ get selectionObject(): GraphObject; /** * Gets or sets the function to execute when this part is selected or deselected. * It is typically used to modify the appearance of the part. * This function must not select or deselect any parts. * * If this property value is a function, it is called with one argument, * this {@link Part} that was selected or that became unselected. * When it is called, the value of {@link Diagram.skipsUndoManager} is temporarily set to true. * By default this property is null. * * This function is called with {@link Diagram.skipsUndoManager} temporarily set to true, * so that any changes to {@link GraphObject}s are not recorded in the {@link UndoManager}. * You do not need to start and commit any transaction in this function. * @see {@link isSelected} * @see {@link selectionAdorned} * @see {@link selectionAdornmentTemplate} */ get selectionChanged(): ((thisPart: Part) => void) | null; set selectionChanged(value: ((thisPart: Part) => void) | null); /** * Gets or sets the adornment template used to create a resize handle {@link Adornment} for this part. * This is used by the {@link ResizingTool}, {@link ToolManager.resizingTool}. * * If an Adornment is supplied, it is normally a {@link Panel.Spot} panel that contains a {@link Placeholder} * with some number of resize handles at the four corners or at the four side midpoints. * @see {@link resizable} * @see {@link resizeObjectName} * @see {@link ResizingTool} */ get resizeAdornmentTemplate(): Adornment | null; set resizeAdornmentTemplate(value: Adornment | null); /** * Gets or sets the name of the {@link GraphObject} that should get a resize handle * when this part is selected. * The value of this property affects the value of {@link resizeObject}. * The initial value is an empty string, meaning the whole {@link Part} itself gets any resize handle. * @see {@link resizable} * @see {@link resizeObject} * @see {@link ResizingTool} */ get resizeObjectName(): string; set resizeObjectName(value: string); /** * This read-only property returns the {@link GraphObject} that should get resize handles when this part is selected. * The value will be in the visual tree of this Part and is usually named with * the value of {@link resizeObjectName}. * @see {@link resizable} * @see {@link resizeObjectName} * @see {@link ResizingTool} */ get resizeObject(): GraphObject; /** * Gets or sets the width and height multiples used when resizing. * By default this property is the Size(NaN, NaN). * @see {@link resizable} * @see {@link resizeObjectName} * @see {@link ResizingTool} */ get resizeCellSize(): Size; set resizeCellSize(value: Size); /** * Gets or sets the adornment template used to create a rotation handle {@link Adornment} for this part. * This is used by the {@link RotatingTool}, {@link ToolManager.rotatingTool}. * * This Adornment should not have a {@link Placeholder} in it, because the RotatingTool will position it away from the * {@link rotateObject} at its {@link GraphObject.angle}. * @see {@link rotatable} * @see {@link rotateObjectName} * @see {@link RotatingTool} */ get rotateAdornmentTemplate(): Adornment | null; set rotateAdornmentTemplate(value: Adornment | null); /** * Gets or sets the name of the {@link GraphObject} that should get a rotate handle * when this part is selected. * The value of this property affects the value of {@link rotateObject}. * The initial value is an empty string, meaning the whole {@link Part} itself gets any rotate handle. * @see {@link rotatable} * @see {@link rotateObject} * @see {@link RotatingTool} */ get rotateObjectName(): string; set rotateObjectName(value: string); /** * This read-only property returns the {@link GraphObject} that should get rotate handles when this part is selected. * The value will be in the visual tree of this Part and is usually named with * the value of {@link rotateObjectName}. * @see {@link rotatable} * @see {@link rotateObjectName} * @see {@link RotatingTool} */ get rotateObject(): GraphObject; /** * Gets or sets the spot on the {@link rotateObject} * that is used in rotating this part with the {@link RotatingTool}. * * Value must be of the type {@link Spot}. * The value must be a specific spot -- i.e. one for which {@link Spot.isSpot} is true, or else `Spot.Default`. * * If the value is `Spot.Default`, the {@link RotatingTool} uses * the locationSpot if the {@link rotateObject} is equal to the {@link locationObject}, otherwise * it uses `Spot.Center`. * * The initial value is `Spot.Default`. * * @see {@link rotateObjectName} * @since 2.0 */ get rotationSpot(): Spot; set rotationSpot(value: Spot); /** * Gets or sets a text string that is associated with this part. * * The initial value is an empty string. * This value is often used for sorting. */ get text(): string; set text(value: string); /** * Gets or sets the {@link Group} of which this {@link Part} or {@link Node} is a member. * This will be null if this is a top-level part. * * You cannot set this property on a {@link Link}; it is set for you automatically * based on the group memberships of the connected nodes. * You cannot set this property on an {@link Adornment} at all. * * A template should not be a member of any group. * @see {@link Group.memberParts} * @see {@link findTopLevelPart} * @see {@link isTopLevel} */ get containingGroup(): Group | null; set containingGroup(value: Group | null); /** * Gets or sets the function that is called after this Part has changed which {@link Group} it belongs to, if any. * It is typically used to modify the appearance of the part. * The first argument will be this Part. * The second argument will be the old Group, or null if it had been a top-level part. * The third argument will be the new Group, or null if it is now a top-level part. * * If the value is a function, that function must not modify the part's containing {@link Group}. * The containing Group has already been changed -- trying to change it again may produce undefined behavior. * * The initial value is null -- no function is called. */ get containingGroupChanged(): ((thisPart: Part, oldGroup: Group | null, newGroup: Group | null) => void) | null; set containingGroupChanged(value: ((thisPart: Part, oldGroup: Group | null, newGroup: Group | null) => void) | null); /** * Return how deep this part is in the hierarchy of nested {@link Group}s. * For parts that have no {@link containingGroup} this returns zero. * * If you want to know how deep a Node is in a tree structure, call {@link Node.findTreeLevel}. */ findSubGraphLevel(): number; /** * Finds the top-level Part for this part, which is itself when {@link isTopLevel} is true. * If this Part is a member of a {@link Group}, this returns the top-level Part for that Group. * If this is a {@link Node} that is a label node for a labeled {@link Link}, this returns the top-level Part for that Link. * * If this is a Node and you are searching for the root of the tree that this node is in, use {@link Node.findTreeRoot}. * @returns This will not return null. */ findTopLevelPart(): Part; /** * This read-only property is true when this part is not member of any {@link Group} node * nor is it a label node for a {@link Link}. * @see {@link containingGroup} * @see {@link Node.labeledLink} */ get isTopLevel(): boolean; /** * This predicate is true if this part is a member of the given {@link Part}, perhaps indirectly. * * If the given part is a {@link Group} and this part is a member of the given group, this returns true. * If this part is a {@link Node} and it is a label node for a link that is a member of the given group, this returns true. * Otherwise this searches recursively any {@link Part.containingGroup} of the given part. * * A part cannot be contained by itself. * A template should not be a member of any group. * * If this is a Node and you want to find whether it is in a subtree whose root is a given Node, use {@link Node.isInTreeOf}. * @param part */ isMemberOf(part: Part | null): boolean; /** * Find the {@link Group} that perhaps indirectly contains both this part and another one. * If this is a Group and it contains the OTHER Part, return this. * If the OTHER Part is a Group and it contains this Part, return that OTHER Part. * * This returns null if the two parts are unrelated in the hierarchy of part membership. * If non-null, the result is a {@link Group}. * * If you want to find the {@link Node} that is the tree parent of two Nodes, * call {@link Node.findCommonTreeParent}. * @param other * @returns may be null */ findCommonContainingGroup(other: Part): Group | null; /** * Gets or sets flags that control when the {@link Layout} that is responsible for this Part is invalidated. * The initial value is {@link LayoutConditions.Standard}, * which causes the layout for this part to be invalidated when the part is added or removed or changes visibility or size. * * Individual layout conditions are provided by {@link LayoutConditions}. * * This property is ignored when {@link isLayoutPositioned} is false -- no operation on this Part * will by itself cause the responsible Layout to be invalidated. * * You can also control when layouts are invalidated is by setting {@link Layout.isInitial} or {@link Layout.isOngoing}. */ get layoutConditions(): LayoutConditions; set layoutConditions(value: LayoutConditions); /** * This predicate is called by Layout implementations to decide whether this Part * should be positioned and might affect the positioning of other Parts. * * This is false if {@link isLayoutPositioned} is false, if {@link isVisible} returns false, * or if the part is in a temporary {@link Layer}. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual */ canLayout(): boolean; /** * Invalidate the {@link Layout} that is responsible for positioning this Part. * If this part is in a {@link Group}, invalidate its {@link Group.layout}, if it has one. * Otherwise invalidate the {@link Diagram.layout}. * * But note that if {@link isLayoutPositioned} is false, or if it is in a temporary {@link Layer}, * or if it is not in a diagram or group, no layout is invalidated. * @param condition - the reason that the layout should be invalidated; * if this argument is not supplied, any value of {@link layoutConditions} other than {@link LayoutConditions.None} * will allow the layout to be invalidated. */ invalidateLayout(condition?: number): void; /** * Gets or sets the function used to determine the location that this Part can be dragged to. * The first argument is a reference to the Part being dragged, the second argument is a Point describing * the proposed location, and the third argument is a snapped location, if one was determined during dragging. * It should return a Point that is the proposed new location. * * By default this function is null and the {@link DraggingTool} uses the snapped location, * if one was determined and if {@link DraggingTool.isGridSnapEnabled} is true, * or the proposed location (the second argument) if not snapping to a grid. * * In either case the {@link DraggingTool} will limit the proposed new location by {@link minLocation} and {@link maxLocation}. * * The function, if supplied, must not have any side-effects. * * An example that limits moving a Node to the current viewport: * ```js * function stayInViewport(part, pt, gridpt) { * const diagram = part.diagram; * if (diagram === null) return pt; * // compute the area inside the viewport * const v = diagram.viewportBounds.copy(); * v.subtractMargin(diagram.padding); * // get the bounds of the part being dragged * const bnd = part.actualBounds; * const loc = part.location; * // now limit the location appropriately * const l = v.x + (loc.x - bnd.x); * const r = v.right - (bnd.right - loc.x); * const t = v.y + (loc.y - bnd.y); * const b = v.bottom - (bnd.bottom - loc.y); * if (l <= gridpt.x && gridpt.x <= r && t <= gridpt.y && gridpt.y <= b) return gridpt; * const p = gridpt.copy(); * if (diagram.toolManager.draggingTool.isGridSnapEnabled) { * // find a location that is inside V but also keeps the part's bounds within V * const cw = diagram.grid.gridCellSize.width; * if (cw > 0) { * while (p.x > r) p.x -= cw; * while (p.x < l) p.x += cw; * } * const ch = diagram.grid.gridCellSize.height; * if (ch > 0) { * while (p.y > b) p.y -= ch; * while (p.y < t) p.y += ch; * } * return p; * } else { * p.x = Math.max(l, Math.min(p.x, r)); * p.y = Math.max(t, Math.min(p.y, b)); * return p; * } * } * ``` * Note that for this functionality you will also probably want to set {@link Diagram.autoScrollRegion} to be a zero margin. * ```js * myDiagram.nodeTemplate = * new go.Node(. . ., * { dragComputation: stayInViewport }, * . . . * ) * ``` * @see {@link maxLocation} * @see {@link minLocation} */ get dragComputation(): ((thisPart: Part, newLoc: Point, snappedLoc: Point) => Point) | null; set dragComputation(value: ((thisPart: Part, newLoc: Point, snappedLoc: Point) => Point) | null); /** * Gets or sets the X and Y offset of this part's shadow. This is only relevant if {@link isShadowed} is true. * The initial value is (6, 6). * @see {@link isShadowed} * @see {@link shadowColor} * @see {@link shadowBlur} */ get shadowOffset(): Point; set shadowOffset(value: Point); /** * Gets or sets the CSS string that describes a shadow color. Default is 'gray'. * Brushes cannot be used for this property -- only strings. * * The opacity of the shadow color is multiplied by the opacity of the shadowed object's brush. * So, for example, if you have a {@link Panel} with a {@link GraphObject.background} * that is "transparent", the shadow that is drawn for the panel will also be transparent. * @see {@link isShadowed} * @see {@link shadowOffset} * @see {@link shadowBlur} */ get shadowColor(): string; set shadowColor(value: string); /** * Gets or sets the numerical value that describes the shadow's blur. Number must be non-negative and non-infinity. * A value of 0 would mean the shadow does not blur and larger numbers represent increasingly more blur. * The total blur area is independent of the Part's area and can become quite large as this number is increased. * * This value is not affected by scale. Default value is 4. * @see {@link isShadowed} * @see {@link shadowOffset} * @see {@link shadowColor} */ get shadowBlur(): number; set shadowBlur(value: number); } /** * An Adornment is a special kind of {@link Part} that is associated with another Part, * the {@link Adornment.adornedPart}. * * Adornments are normally associated with a particular {@link GraphObject} in the adorned Part -- * that is the value of {@link adornedObject}. * However, the {@link adornedObject} may be null, in which case the {@link adornedPart} will also be null. * * The area occupied by the adorned object is represented in the Adornment's visual tree by a {@link Placeholder}. * The placeholder is always the {@link Part.locationObject}, * although you may specify any {@link Spot} as the {@link Part.locationSpot}. * An adornment need not have a placeholder, but it may have at most one. * * Adornments can be distinguished by their {@link Part.category}. * This property can be an arbitrary string value determined by the code creating the adornment, * typically a tool that wants to be able to tell various adornments apart from each other. * Use the {@link Part.findAdornment} method to find an adornment for a part of a given category. * * For example, one of the Adornments created by {@link Part.updateAdornments} when the part * {@link Part.isSelected} has the {@link Part.category} of "Selection". * Those created by {@link ResizingTool.updateAdornments} have a category of "Resize" * and normally contain eight resize handles. * * Besides the selection Adornment and tool Adornments, Adornments are also used for * context menus and tooltips. * The {@link adornedObject} in such cases refers to the {@link GraphObject} to which the * the context menu or tooltip applies. * * There cannot be any links connected to an Adornment, * nor can an Adornment have members or be a member of a group. * * An Adornment cannot have its own Adornments. * An Adornment cannot be selected. * * Adornments are not positioned by a {@link Layout} because they are normally positioned * according to the Part that they adorn. * * For more discussion and examples, see Selection, * ToolTips, * Context Menus, and * Tools. */ export class Adornment extends Part { /** * Constructs an empty Adornment of the given {@link type}. Default type is {@link Panel.Position}. * The panel type must be one of the {@link PanelLayout} static values (e.g. {@link Panel.Position}). * The string value such as "Auto" may also be used. * * Usage example: * *```js * // Constructs an Adornment, sets properties on it, * // adds a data binding to it, * // and adds two GraphObjects to the Adornment: * const a = new go.Adornment("Auto", { * margin: 5, * background: "red" * }) * .add( * new go.Shape("RoundedRectangle")), * new go.TextBlock("Some Text") * ) * ``` * * @param type - a string or a PanelLayout, such as "Horizontal" or {@link Panel.Vertical}. * If not supplied, the default Panel type is "Position". * @param init - Optional initialization properties. */ constructor(type?: PanelLayout | string, init?: Partial); /** * Constructs an empty Panel. Default type is {@link Panel.Position}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * This read-only property returns a {@link Placeholder} that this Adornment may contain in its visual tree. * This may be null if there is no such placeholder object in the visual tree of this Adornment. * * There may be at most one Placeholder in an Adornment. * The Placeholder determines the {@link Part.location} for the Adornment, when it is visible. * When there is a Placeholder, the {@link Part.locationObjectName} is ignored and the * {@link Part.locationObject} will be this Placeholder. */ get placeholder(): Placeholder | null; /** * Gets or sets the {@link GraphObject} that is adorned. * Setting this property updates the adorned object's Part by calling {@link Part.addAdornment}. * This may be null if the Adornment does not adorn a particular object. */ get adornedObject(): GraphObject | null; set adornedObject(value: GraphObject | null); /** * This read-only property returns the {@link Part} that contains the adorned object. * This will be null if the {@link adornedObject} is null. */ get adornedPart(): Part | null; } /** * This enumeration specifies possible values for {@link Node.portSpreading}. * @since 3.0 */ export declare enum PortSpreading { /** * Links connecting with a port should all connect at a single point on the side(s) indicated by a Spot that is {@link Spot.isSide}. */ None = 0, /** * Links connecting with a port should be distributed evenly along the side(s) indicated by a Spot that is {@link Spot.isSide}. This is the default value. */ Evenly = 1, /** * Links connecting with a port should packed together based on the link's shape's width on the side(s) indicated by a Spot that is {@link Spot.isSide}. */ Packed = 2 } /** * A Node is a {@link Part} that may connect to other nodes with {@link Link}s, * or that may be a member of a {@link Group}. * * {@link Group} inherits from Node, * enabling nodes to logically contain other nodes and links. *

* For a more general discussion of how to define nodes, see Introduction to Nodes. * * Although you can create a Node and {@link Diagram.add} it to a Diagram, this does not update the Model. * It is more common to create a node by adding a node data object to the model * by calling {@link Model.addNodeData}. For example: * ```js * myDiagram.startTransaction("make new node"); * myDiagram.model.addNodeData({ key: "Omega" }); * myDiagram.commitTransaction("make new node"); * ``` * * This will cause a Node or simple {@link Part} to be created (copying the template found in {@link Diagram.nodeTemplateMap}), * added to the Diagram in some {@link Layer} (based on {@link Part.layerName}), and bound to the node data * (resulting in {@link Panel.data} referring to that node data object). * If you do not keep a reference to that JavaScript object, as the above code does not, * you can retrieve it later by calling {@link Model.findNodeDataForKey}. * * It is very common to initialize a Diagram by setting {@link Model.nodeDataArray} to a JavaScript Array * of JavaScript objects holding the properties that you need in your model. * Nearly all of the samples do this kind of initialization. * * You can delete a Node by either calling {@link Diagram.remove} or by calling {@link Model.removeNodeData}. * The latter obviously will modify the Model; the former does so if the Node was created from model data. * Commands such as {@link CommandHandler.deleteSelection} call these methods within a transaction. * * You can find all of the {@link Link}s that are connected with a Node by calling {@link findLinksConnected}. * Because links normally have a direction, you can find all of the links that have their {@link Link.toNode} * be a given Node by calling {@link findLinksInto}. * Similarly, you can call {@link findLinksOutOf} to find all of the links coming out from a node; * such links have their {@link Link.fromNode} be that node. * For tree-structured graphs, use {@link findTreeChildrenLinks} or {@link findTreeParentLink}. * * If you are not so interested in the links but are interested in the nodes at the other end of the links * connecting with a node, there are other methods that you can call. * {@link findNodesConnected} returns all of the nodes that are at the other end of the links that * connect with a given node. * {@link findNodesInto} and {@link findNodesOutOf} return the subsets of those nodes considering * only those links that go into or come out of the given node. * For tree-structured graphs, use {@link findTreeChildrenNodes} or {@link findTreeParentNode}. * * For example, to operate on the data of all of the destination nodes: * ```js * const it = somenode.findNodesOutOf(); * while (it.next()) { * const child = it.value; * if (child.data.text.indexOf("special") >= 0) { ... } * } * ``` * * You can link two nodes by creating a new {@link Link}, setting its {@link Link.toNode} and {@link Link.fromNode} * (in either order), and {@link Diagram.add}ing it to the diagram. * But it is more common to add a link data object to the {@link Diagram.model} by calling {@link GraphLinksModel.addLinkData}. * Just creating and adding a {@link Link} will not update the model. * * Thus to add a link when using a {@link GraphLinksModel} you should do something like: * ```js * myDiagram.startTransaction("make new link"); * myDiagram.model.addLinkData({ from: "Alpha", to: "Beta" }); * myDiagram.commitTransaction("make new link"); * ``` * * Where you would substitute the keys of the actual nodes that you want to connect with a link. * If you are using a {@link TreeModel}, there are no link data objects, so you just need to call * {@link TreeModel.setParentKeyForNodeData} to specify the "parent" node's key for a "child" node data. * * To find a {@link Link} given a link data object in the {@link GraphLinksModel}, * call {@link Diagram.findLinkForData}. When using a {@link TreeModel}, call either {@link Diagram.findNodeForData} * or {@link Diagram.findNodeForKey} to get a Node, and then call {@link findTreeParentLink} to get the Link, if any exists. * * To find a link that connects two nodes, call {@link findLinksTo} or {@link findLinksBetween}. * With the former method, the direction matters; with the latter method it returns links in either direction. * * As links connect with a node or are disconnected, you may want to update the appearance of the node. * You can set the {@link linkConnected} and {@link linkDisconnected} properties to be functions that are called. * These functions must not modify any link relationships -- the properties just exist to update the appearance of the node. * A typical usage would be to change the color or figure of a shape. * * You can control whether the user may draw a new link or reconnect a link between a pair of Nodes * by affecting the result of {@link LinkingBaseTool.isValidLink}. * You can override that predicate on {@link LinkingTool} and {@link RelinkingTool}, * but it is easier to set the {@link linkValidation} or * {@link LinkingBaseTool.linkValidation} functional property. *

* For a more general discussion of validation, see Introduction to Validation. * * Nodes also support the ability to provide logical and physical distinctions in the connection points * that links use at a node. These connection objects are called "ports". * By default the port object will be the whole {@link Node}. * However, you can set the {@link GraphObject.portId} property on any {@link GraphObject} in the visual tree of a node * to cause that element to be treated as a "port". * The "port id" is just a string that ought to be unique amongst all of the port elements in the node. * * In the case of a node only having a single port, you should set the {@link GraphObject.portId} as an empty string. * When there is no such element declared as the default port, it uses the whole node. * You can use the {@link port} property to get the only port element. * * When a node should have multiple ports, * i.e. multiple {@link GraphObject}s acting as separate connection points for links, * you should set each port's {@link GraphObject.portId} to a string value that is unique for the node. * When there may be multiple ports on a node, you can get a collection of elements representing ports * by using the {@link ports} property. * Use the {@link findPort} method to find a particular port element by name. * * Note: the only kind of model that can save port information, i.e. portIds that are not an empty string, * for links is a {@link GraphLinksModel} whose {@link GraphLinksModel.linkFromPortIdProperty} and * {@link GraphLinksModel.linkToPortIdProperty} have been set to name properties on the link data objects. *

* For a more general discussion of ports, see Introduction to Ports. * * All of the "findLinks..." and "findNodes..." methods mentioned above take an optional port id argument. * When no argument is passed, these methods consider all links connecting with the node. * When a port id argument is provided, these methods only consider links that connect with that port * in the given node. * Thus when navigating through the diagram, you can easily look at all of the nodes that links coming out of * a given node go to. Or you can just look at those nodes at the ends of links coming out of a particular port. * * You can also control the default connecting behavior of {@link Link}s at each port. * Because a port can be any {@link GraphObject}, they are all properties on GraphObject. * The properties are duplicated so that you can guide the "from" ends of links differently from the "to" ends of links. * The properties include: * - {@link GraphObject.fromSpot}, {@link GraphObject.toSpot} * - {@link GraphObject.fromEndSegmentLength}, {@link GraphObject.toEndSegmentLength} * - {@link GraphObject.fromShortLength}, {@link GraphObject.toShortLength} * - {@link GraphObject.fromLinkable}, {@link GraphObject.toLinkable} * - {@link GraphObject.fromLinkableDuplicates}, {@link GraphObject.toLinkableDuplicates} * - {@link GraphObject.fromLinkableSelfNode}, {@link GraphObject.toLinkableSelfNode} * - {@link GraphObject.fromMaxLinks}, {@link GraphObject.toMaxLinks} * * The "...Spot" and "...Length" properties control the position and routing of links at a port. * The "...Linkable..." and "...MaxLinks" properties control whether or not users can draw a new link * or reconnect an existing link from or to a port. * (The "...Spot" and "...Length" properties also exist on {@link Link}, to override for a particular * link the default values that come from a port element.) *

* For a more general discussion of link points, see Introduction to Link Connection Points. * * When the graph is tree-structured, you can use several functions for traversing the tree: * - {@link findTreeParentNode} * - {@link findTreeChildrenNodes} * - {@link findTreeParentLink} * - {@link findTreeChildrenLinks} * - {@link findTreeRoot} * - {@link findTreeParentChain} * - {@link findTreeParts} * - {@link findCommonTreeParent} * - {@link isInTreeOf} * - {@link findTreeLevel} * * Determining whether a tree grows from the root via links that go out to the children or vice-versa * is controlled for the whole diagram by the {@link Diagram.isTreePathToChildren} property. * However an individual link will be ignored by the above functions if {@link Link.isTreeLink} is false. * * The Node class also supports the notion of expanding and collapsing a subtree of nodes and links, * causing those nodes and links to be shown or hidden. * Principally this is a matter of setting {@link Node.isTreeExpanded}. * Of course if the diagram's graph is not tree-structured, these concepts and properties might not apply. * * If you want to change the appearance of the node you can do so in a function that you assign to * the {@link treeExpandedChanged} property. * This function must not modify any link relationships or expand or collapse any subtrees -- the property just exists * to update the appearance of the node. * * There is an option for link routing to try to avoid crossing over nodes: * {@link Link.routing} = {@link Routing.AvoidsNodes}. * You can control whether such links should avoid or ignore a node by setting {@link avoidable}. * Set {@link avoidableMargin} to control the area beyond the {@link GraphObject.actualBounds} * where AvoidsNodes links should not go. *

* For more discussion and examples, see Nodes, * Ports, and * Link Points. *

* For more about trees, see Trees, and * SubTrees. *

* To customize user-resizing behavior, please read * Introduction to the ResizingTool. * To customize user-rotating behavior, please read * Introduction to the RotatingTool. * * Only Nodes that are in Diagrams can have connections via Links. * Templates should not be connected with Links, be labels of Links, be members of Groups, or have any Adornments. */ export class Node extends Part { /** * Constructs an empty Node of the given {@link type}. Default type is {@link Panel.Position}. * The panel type must be a {@link PanelLayout} such as {@link Panel.Position}. * The string value such as "Auto" may also be used. * * Usage example: * *```js * // Constructs a Node, sets properties on it, * // adds a data binding to it, * // and adds two GraphObjects to the Node: * const n = new go.Node("Auto", { * margin: 5, * background: "red" * }) * .bind("location", "loc", go.Point.parse) * .add( * new go.Shape("RoundedRectangle"), * new go.TextBlock("Some Text") * ); * ``` * * @param type - a string or PanelLayout, such as "Horizontal" or {@link Panel.Vertical}. * If not supplied, the default Panel type is "Position". * @param init - Optional initialization properties. */ constructor(type?: PanelLayout | string, init?: Partial); /** * Constructs an empty Panel. Default type is {@link Panel.Position}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * @deprecated See {@link PortSpreading.None}. */ static readonly SpreadingNone = PortSpreading.None; /** * @deprecated See {@link PortSpreading.Evenly}. */ static readonly SpreadingEvenly = PortSpreading.Evenly; /** * @deprecated See {@link PortSpreading.Packed}. */ static readonly SpreadingPacked = PortSpreading.Packed; /** * (undocumented) * @param other * @param thisportid * @param otherportid */ invalidateLinkBundle(other: Node, thisportid?: string, otherportid?: string): void; /** * (undocumented) * This invalidates the routes of all links connected to this node. * Basically this calls {@link Link.invalidateRoute} on all connected links * and invalidates any cached side-connection information. * @param ignore - An optional set of {@link Link}s to ignore. */ invalidateConnectedLinks(ignore?: Set): void; /** * Gets or sets how link points are computed when the port spot is a "side" spot. * The value must be one of {@link PortSpreading.None|SpreadingNone}, * {@link PortSpreading.Evenly|SpreadingEvenly}, {@link PortSpreading.Packed|SpreadingPacked}. * The default value is {@link PortSpreading.Evenly}. */ get portSpreading(): PortSpreading; set portSpreading(value: PortSpreading); /** * Gets or sets whether this Node is to be avoided by {@link Link}s * whose {@link Link.routing} is {@link Routing.AvoidsNodes}. * * The default value is true. */ get avoidable(): boolean; set avoidable(value: boolean); /** * Gets or sets the margin around this Node in which avoidable links will not be routed. * * You may need to increase the {@link fromEndSegmentLength} and {@link toEndSegmentLength} in * order to prevent link routes from turning within the avoidable area around the Node. * * Value must be of type Margin. * The default margin is Margin(2,2,2,2) */ get avoidableMargin(): MarginLike; set avoidableMargin(value: MarginLike); /** * Return the area to be avoided for this node -- the node's {@link GraphObject.actualBounds} * plus the {@link Node.avoidableMargin}. * @virtual * @param result - a {@link Rect} to be modified and returned. * @returns the area in document coordinates. * @since 2.2 */ getAvoidableRect(result: Rect): Rect; /** * Starting with this node, walk up the chain of containingGroups to find a node that is visible. * This can be overridden to find a tree-parent/ancestor if the reason that this node * is not visible is because of a collapsed tree rather than a collapsed group. * @virtual * @since 2.2 */ findVisibleNode(): Node | null; /** * This read-only property returns an iterator over all of the {@link Link}s that are connected with this node. * This includes both links that are coming out of this node as well as links that are going into this node. * Setting {@link Link.fromNode} or {@link Link.toNode} to refer to this Node * will add that {@link Link} to this collection. * * Use the {@link findLinksConnected}, {@link findLinksOutOf}, or {@link findLinksInto} methods * to get different subsets of the links, depending on direction or depending on connecting to a particular port. * * A template should not have any links connected with it. */ get linksConnected(): Iterator; /** * Return a collection of Links that connect with this Node or any in its subtree, excluding any isTreeLink Links. * For trees this is the analog of {@link Group.findExternalLinksConnected} for Groups. * @since 2.2 */ findExternalTreeLinksConnected(): Iterator; /** * Returns an iterator over all of the {@link Link}s that connect with this node in either direction, * perhaps limited to the given port id on this node. * @virtual * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findLinksConnected(pid?: string | null): Iterator; /** * Returns an iterator over all of the {@link Link}s that come out of this node, * perhaps limited to the given port id on this node. * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findLinksOutOf(pid?: string | null): Iterator; /** * Returns an iterator over all of the {@link Link}s that go into this node, * perhaps limited to the given port id on this node. * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findLinksInto(pid?: string | null): Iterator; /** * Returns an iterator over the {@link Node}s that are connected with this node * in either direction, perhaps limited to the given port id on this node. * * The results may include this node itself if there is a reflexive link connecting this node with itself. * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findNodesConnected(pid?: string | null): Iterator; /** * Returns an iterator over the {@link Node}s that are connected with this node * by links coming out of this node, perhaps limited to the given port id on this node. * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findNodesOutOf(pid?: string | null): Iterator; /** * Returns an iterator over the {@link Node}s that are connected with this node * by links going into this node, perhaps limited to the given port id on this node. * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findNodesInto(pid?: string | null): Iterator; /** * Returns an iterator over all of the {@link Link}s that go from this node to another node or vice-versa, * perhaps limited to a given port id on this node and a port id on the other node. * * If you want all of the links between two nodes in just one direction, use {@link findLinksTo}. * @param othernode * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. * @param otherpid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findLinksBetween(othernode: Node, pid?: string | null, otherpid?: string | null): Iterator; /** * Returns an iterator over all of the {@link Link}s that go from this node to another node, * perhaps limited to a given port id on this node and a port id on the other node. * * If you want all of the links between two nodes in both directions, use {@link findLinksBetween}. * @param othernode * @param pid - A port identifier string; if null the link's portId is ignored and all links are included in the search. * @param otherpid - A port identifier string; if null the link's portId is ignored and all links are included in the search. */ findLinksTo(othernode: Node, pid?: string | null, otherpid?: string | null): Iterator; /** * Gets or sets the function that is called after a {@link Link} has been connected with this Node. * It is typically used to modify the appearance of the node. * The first argument will be this Node. * The second argument will be a Link that is now connected with this node. * The third argument will be a GraphObject port indicating which port the link was connected with. * * If the value is a function, that function must not modify what this Node is connected with. * The Link has already been added -- trying to remove it or another link may produce undefined behavior. * However, the other end of the link may not yet have been connected with a node (and might never be), * so you cannot depend on looking at what the link connects with. * * The default value is null -- no function is called. */ get linkConnected(): ((thisNode: Node, newLink: Link, thisPort: GraphObject) => void) | null; set linkConnected(value: ((thisNode: Node, newLink: Link, thisPort: GraphObject) => void) | null); /** * Gets or sets the function that is called after a {@link Link} has been disconnected from this Node. * It is typically used to modify the appearance of the node. * The first argument will be this Node. * The second argument will be a Link that had been connected with this node. * The third argument will be a GraphObject port indicating which port the link had been connected with. * * If the value is a function, that function must not modify what this Node is connected with. * The Link has already been removed -- trying to add it or another link may produce undefined behavior. * The other end of the link may not yet have been disconnected from a node (and might never be), * so you cannot depend on looking at what the link connects with. * * The default value is null -- no function is called. */ get linkDisconnected(): ((thisNode: Node, oldLink: Link, thisPort: GraphObject) => void) | null; set linkDisconnected(value: ((thisNode: Node, oldLink: Link, thisPort: GraphObject) => void) | null); /** * Gets or sets a predicate that determines whether or not a Link may be connected with this node. * If this is non-null, the predicate is called in addition to the predicate that is {@link LinkingBaseTool.linkValidation} * on the {@link LinkingTool} and {@link RelinkingTool}. * See {@link LinkingBaseTool.isValidLink} for more details. * * The default predicate is null, which is equivalent to simply returning true. * The first argument will be the proposed "from" Node (may be null). * The second argument will be the proposed "from" GraphObject port (may be null). * The third argument will be the proposed "to" Node (may be null). * The fourth argument will be the proposed "to" GraphObject port (may be null). * The fifth argument may be null when asking about creating a new link, * or may be a Link when asking about reconnecting an existing link. * * The function, if supplied, must not have any side-effects. */ get linkValidation(): ((fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean) | null; set linkValidation(value: ((fromNode: Node, fromPort: GraphObject, toNode: Node, toPort: GraphObject, link: Link) => boolean) | null); /** * This read-only property is true when this Node is a label node for a Link. * * If this is true, then `n.labeledLink` will be a Link and `n.labeledLink.isLabeledLink` will be true. * @see {@link labeledLink} */ get isLinkLabel(): boolean; /** * Gets or sets the {@link Link} for which this Node is acting as a smart label. * Most nodes do not act as link labels, so this property will be null. * * A template should not be a label node for a link. * @see {@link isLinkLabel} */ get labeledLink(): Link | null; set labeledLink(value: Link | null); /** * (undocumented) * Called by Link when routing, in case a port element is not visible. * @param port - a port element, presumably with portId not null * @returns the port itself if it isVisibleObject() or else the default port of the Node */ findVisiblePort(port: GraphObject): GraphObject; /** * Find a {@link GraphObject} with a given {@link GraphObject.portId}. * If no such GraphObject is found, search for one with the empty string as its port identifier. * Finally, when failing to find a port with either the given name or the empty string, * this method returns this whole node itself. * @param pid */ findPort(pid: string): GraphObject; /** * This read-only property returns the primary {@link GraphObject} representing a port in this node. * If there is a GraphObject whose {@link GraphObject.portId} is the empty string, return it. * If there is no such element, just return this whole Node. */ get port(): GraphObject; /** * This read-only property returns an iterator over all of the {@link GraphObject}s in this node that act as ports. */ get ports(): Iterator; /** * This predicate is true if this node is a child of the given {@link Node}, perhaps indirectly as a descendant. * * If this node is a child of the given node according to {@link Diagram.isTreePathToChildren}, this returns true. * Otherwise this searches recursively the chain of tree parents of this node, * ignoring links for which {@link Link.isTreeLink} is false. * A node cannot be in its own subtree. * * If you what to find out whether this Node is (perhaps indirectly) contained by a Group, use {@link Part.isMemberOf}. * @param node - the Node that might be a parent or ancestor of this node. * @returns true if the given node is an ancestor of this node, but false otherwise, including false if it is the same node. * @see {@link findTreeRoot} * @see {@link findTreeParentChain} */ isInTreeOf(node: Node): boolean; /** * Return the {@link Node} that is at the root of the tree that this node is in, perhaps this node itself. * * This node will be {@link isInTreeOf} the resulting node, unless the resulting node is this node itself. * The graph traversal will ignore links for which {@link Link.isTreeLink} is false. * * If you want to search up the containment hierarchy of {@link Group}s, use {@link Part.findTopLevelPart}. * @returns If this Node has no "tree parent", this returns itself. * @see {@link Diagram.isTreePathToChildren} * @see {@link findTreeParentChain} */ findTreeRoot(): Node; /** * Find the {@link Node} that is the perhaps indirect tree parent of both this node and another one, * or this node if it is an ancestor of the other node, or vice-versa. * * If you want to find the {@link Group} that contains two Parts, call {@link Part.findCommonContainingGroup}. * @param other * @returns may be null if in different trees, * or may be itself if the OTHER argument is THIS node, * or may be itself if the OTHER node is a descendant of THIS node, * or may be the OTHER node if THIS node is in the tree of the OTHER node. * @see {@link findTreeRoot} * @see {@link findTreeParentChain} */ findCommonTreeParent(other: Node): Node | null; /** * Returns the {@link Link} that connects with the tree parent {@link Node} of this node if the graph is tree-structured, * if there is such a link and {@link Link.isTreeLink} is true. * @returns The Link to the parent Node, or null if there is no parent node. * @see {@link findTreeParentNode} * @see {@link findTreeChildrenLinks} * @see {@link Diagram.isTreePathToChildren} * @see {@link findTreeRoot} * @see {@link findTreeParentChain} */ findTreeParentLink(): Link | null; /** * Returns the {@link Node} that is the tree parent of this node if the graph is tree-structured, if there is a parent. * Links for which {@link Link.isTreeLink} is false are ignored. * @returns The parent Node, or null if there is no parent node. * @see {@link findTreeParentLink} * @see {@link findTreeChildrenNodes} * @see {@link Diagram.isTreePathToChildren} * @see {@link findTreeRoot} * @see {@link findTreeParentChain} */ findTreeParentNode(): Node | null; /** * Return a collection of {@link Part}s including this {@link Node}, * its tree parent link and node, and so on up the chain to the root node. * * This calls {@link findTreeParentLink} and {@link findTreeParentNode}. * Links for which {@link Link.isTreeLink} is false are ignored. * * This may result in undefined behavior if there are cycles of Links that are {@link Link.isTreeLink}. * * The result will include this node and the "root" node and all nodes and links in between. * The root node is also accessible directly via {@link findTreeRoot}. * If any of the nodes are {@link Group}s, their member parts are not included. * @returns A Set of Nodes and Links. * @see {@link findTreeRoot} * @see {@link findTreeParts} */ findTreeParentChain(): Set; /** * Return how deep this node is in a tree structure. * For tree root nodes, this returns zero. * This calls {@link findTreeParentNode} to find any tree parent node, * so this respects {@link Diagram.isTreePathToChildren} and {@link Link.isTreeLink} * to know which way to traverse links and to know to ignore non-tree links. * * This may result in undefined behavior if there are cycles of Links that are {@link Link.isTreeLink}. * * If you want to know how deep a Part is nested inside Groups, call {@link Part.findSubGraphLevel}. * @see {@link findTreeRoot} * @see {@link findTreeParentChain} */ findTreeLevel(): number; /** * Returns an {@link Iterator} for the collection of {@link Link}s that connect with the immediate tree children of this node. * Links for which {@link Link.isTreeLink} is false are ignored. * * This basically returns either {@link findLinksOutOf} or {@link findLinksInto}, * depending on {@link Diagram.isTreePathToChildren}, * but the results excludes links for which {@link Link.isTreeLink} is false. * @see {@link findTreeParentLink} * @see {@link findTreeChildrenNodes} * @see {@link findTreeParts} */ findTreeChildrenLinks(): Iterator; /** * Returns an {@link Iterator} for the collection of {@link Node}s that are the immediate tree children of this node. * Nodes only connected by links for which {@link Link.isTreeLink} is false are ignored. * * This basically returns either {@link findNodesOutOf} or {@link findNodesInto}, * depending on {@link Diagram.isTreePathToChildren}. * @see {@link findTreeParentNode} * @see {@link findTreeChildrenLinks} * @see {@link findTreeParts} */ findTreeChildrenNodes(): Iterator; /** * Return a collection of {@link Part}s including this {@link Node}, * all of the {@link Link}s going to child {@link Node}s, and all of their * tree child nodes and links. * Links for which {@link Link.isTreeLink} is false are ignored. * * Whether child nodes are found for a parent node by following links out of the parent node or * by links coming into the parent node is determined by the value of {@link Diagram.isTreePathToChildren}. * * The result will include this, the "root" node. * If any of the nodes are {@link Group}s, their member parts are not included. * * If you want to find the collection of Parts that are contained by a {@link Group}, use {@link Group.findSubGraphParts}. * @param level - How many levels of the tree, starting at this node, to include; * the default is Infinity, including all tree children of this node. Values less than 1 are treated as 1. * @returns A Set of Nodes and Links. * @see {@link findTreeChildrenNodes} * @see {@link findTreeChildrenLinks} * @see {@link findTreeParentChain} */ findTreeParts(level?: number): Set; /** * Hide each child node and the connecting link, * and recursively collapse each child node. * This changes the value of {@link Part.isVisible} of the whole subtree and the parts owned by * those nodes and links. * However, this root node's visibility is unchanged. * * Links are assumed to go from the parent node to the children nodes, * unless {@link Diagram.isTreePathToChildren} is false. * Links for which {@link Link.isTreeLink} is false are ignored. * * This sets {@link isTreeExpanded} to false on this node and on all of the children nodes. * For those child nodes that were expanded when they were collapsed, * {@link wasTreeExpanded} is set to true. * * You can also pass in a number of levels to hide nodes beyond a certain level starting at this node. * If you want to make sure that all nodes are expanded up to a particular level, call {@link expandTree}. * If you want to do both, call `expandTree` before calling `collapseTree` to * collapse nodes expanded due to the {@link wasTreeExpanded} flag. * * This method does not perform a transaction or start any animation. * You may want to call the {@link CommandHandler.collapseTree} command, which does perform a transaction * and raise a {@link DiagramEvent}. * * To collapse a {@link Group}'s subgraph of {@link Node}s and {@link Link}s, use {@link Group.collapseSubGraph}. * @param level - How many levels of the tree, starting at this node, to keep expanded if already expanded; * the default is 1, hiding all tree children of this node. Values less than 1 are treated as 1. * @see {@link expandTree} * @see {@link findTreeParts} */ collapseTree(level?: number): void; /** * Show each child node and the connecting link, * and perhaps recursively expand their child nodes. * This may change the value of {@link Part.isVisible} of the whole subtree and the parts owned by * those nodes and links. * However, this root node's visibility is unchanged. * * This sets {@link isTreeExpanded} to true on this node and on all of the children nodes. * Links are assumed to go from the parent node to the children nodes, * unless {@link Diagram.isTreePathToChildren} is false. * Links for which {@link Link.isTreeLink} is false are ignored. * * This will expand a tree child node only if its {@link wasTreeExpanded} property was true. * * You can also pass in a number of levels in order to be sure that all nodes * starting at this node and up through that number of levels are visible. * If you want to make sure that there are no nodes expanded after a particular level, call {@link collapseTree}. * If you want to do both, call `expandTree` before calling `collapseTree` to * collapse nodes expanded due to the {@link wasTreeExpanded} flag. * * This method does not perform a transaction or start any animation. * You may want to call the {@link CommandHandler.expandTree} command, which does perform a transaction * and raise a {@link DiagramEvent}. * * To expand a {@link Group}'s subgraph of {@link Node}s and {@link Link}s, use {@link Group.expandSubGraph}. * @param level - How many levels of the tree should be expanded; * the default is 2, showing all tree children of this node and potentially more. * Values less than 2 are treated as 2. * @see {@link collapseTree} * @see {@link findTreeParts} */ expandTree(level?: number): void; /** * Gets or sets whether the subtree graph starting at this node is expanded. * Changing this property's value will call {@link collapseTree} or {@link expandTree}, * and also will call the value of {@link treeExpandedChanged} if it is a function. * * The initial value is true -- "tree-child" nodes, and the links to them, are shown. * * There is an analogous property for expanded/collapsed {@link Group}s: {@link Group.isSubGraphExpanded}. */ get isTreeExpanded(): boolean; set isTreeExpanded(value: boolean); /** * Gets or sets whether the subtree graph starting at this node * had been collapsed by a call to {@link expandTree} on the parent node. * The initial value is false. * @see {@link isTreeExpanded} */ get wasTreeExpanded(): boolean; set wasTreeExpanded(value: boolean); /** * Gets or sets the function that is called when {@link isTreeExpanded} has changed value. * The argument to that function will be this Node. * * If the value is a function, that function must not expand or collapse any trees of nodes and links. * The Node has already been expanded or collapsed -- trying to change it again may produce undefined behavior. * * The default value is null -- no function is called. */ get treeExpandedChanged(): ((thisNode: Node) => void) | null; set treeExpandedChanged(value: ((thisNode: Node) => void) | null); /** * Gets whether this node has no tree children. * * The initial value is true, meaning that there are no links connected with child nodes * in the direction given by {@link Diagram.isTreePathToChildren}. * This value changes automatically as link connections are added to or removed from this node. * Links for which {@link Link.isTreeLink} is false are ignored. * @readonly */ get isTreeLeaf(): boolean; set isTreeLeaf(value: boolean); /** * Gets whether this node has no tree parent. * * This calls {@link findTreeParentLink} to see if a valid parent link connects with this node. * If there is no such link, this node must be a "root" node. * @readonly * @since 3.0 */ get isTreeRoot(): boolean; } /** * This enumeration specifies possible values for {@link Link.adjusting}. * @since 3.0 */ export declare enum LinkAdjusting { /** * The link route computation does not depend on any previous route points. */ None = 0, /** * The link route computation should keep the intermediate points of the previous route, * just modifying the first and/or last points; * if the routing is orthogonal, it will only modify the first two and/or last two points. */ End = 17, /** * The link route computation should scale and rotate the intermediate points so that the link's shape looks approximately the same; * if the routing is orthogonal, this value is treated as if it were {@link End}. */ Scale = 18, /** * The link route computation should linearly interpolate the intermediate points so that the link's shape looks stretched; * if the routing is orthogonal, this value is treated as if it were {@link End}. */ Stretch = 19 } /** * This enumeration specifies possible values for {@link Link.routing}. * @since 3.0 */ export declare enum Routing { /** * The route goes fairly straight between ports. */ Normal = 1, /** * Each segment is horizontal or vertical. */ Orthogonal = 2, /** * Each segment is horizontal or vertical, but the route tries to avoid crossing over nodes. */ AvoidsNodes = 6 } /** * This enumeration specifies possible values for {@link Link.curve}. * @since 3.0 */ export declare enum Curve { /** * The path geometry consists of straight line segments. */ None = 0, /** * The link path uses Bezier curve segments. */ Bezier = 9, /** * Orthogonal link segments will be discontinuous where they cross over other orthogonal link * segments that have a {@link Link.curve} of JumpOver or JumpGap. */ JumpGap = 10, /** * Orthogonal link segments will veer around where they cross over other orthogonal link * segments that have a {@link Link.curve} of JumpOver or JumpGap. */ JumpOver = 11 } /** * A Link is a {@link Part} that connects {@link Node}s. * The link relationship is directional, going from {@link Link.fromNode} to {@link Link.toNode}. * A link can connect to a specific port element in a node, as named by the {@link Link.fromPortId} * and {@link Link.toPortId} properties. *

* For more discussion, see Introduction to Links. * * To add a Link to a Diagram when using a {@link GraphLinksModel} you should do something like: * ```js * myDiagram.startTransaction("make new link"); * myDiagram.model.addLinkData({ from: "Alpha", to: "Beta" }); * myDiagram.commitTransaction("make new link"); * ``` * * where you would substitute the keys of the actual nodes that you want to connect with a link. * This will cause a Link to be created (copying the template found in {@link Diagram.linkTemplateMap}), * added to the Diagram in some {@link Layer} (based on {@link Part.layerName}), and bound to the link data * (resulting in {@link Panel.data} referring to that link data object). * Note that link data objects, unlike {@link Node} data, do not have their own unique keys or identifiers, * because other Parts do not refer to them. * * If you are using a {@link TreeModel}, there are no link data objects, so you just need to call * {@link TreeModel.setParentKeyForNodeData} to specify the "parent" node's key for a "child" node data. * * To find a {@link Link} given a link data object in the {@link GraphLinksModel}, * call {@link Diagram.findLinkForData}. When using a {@link TreeModel}, call either {@link Diagram.findNodeForData} * or {@link Diagram.findNodeForKey} to get a Node, and then call {@link Node.findTreeParentLink} to get the Link, if any exists. * * To find a link that connects two nodes, call {@link Node.findLinksTo} or {@link Node.findLinksBetween}. * With the former method, the direction matters; with the latter method it returns links in either direction. * * A link's position and size are determined by the two node ports that it connects. * Normally there should be a {@link Shape} as the main element in this Link. * This shape is what users will see as the "line" or "wire" -- * you can set its {@link Shape.stroke} and other "stroke..." properties to control its appearance. * You can get that Shape easily via the {@link path} property. * * The link will compute a route (a sequence of points) going from the {@link fromNode}'s port element * to the {@link toNode}'s port element. * That route is used to generate the path of the main shape. * Properties that affect the nature of the route and the geometry of the path include: * - {@link curve} * - {@link curviness} * - {@link corner} * - {@link routing} * - {@link smoothness} * - {@link adjusting} * *

* For more discussion and examples, see Links. * * There are additional properties that affect how the end of the link connects to a port element of a node. * There are duplicate properties, ones for the "to" end and ones for the "from" end: * - {@link fromSpot}, {@link toSpot} * - {@link fromEndSegmentLength}, {@link toEndSegmentLength} * - {@link fromShortLength}, {@link toShortLength} * * These properties normally have "default" values, causing the link's routing and path-geometry generating * to get the corresponding values from the connected port element. * This scheme permits an individual link to have its own specific connection to a port, * taking precedence over how the port normally expects links to connect to it. * For example, several of the {@link Layout} classes sets these properties on each Link * as part of their route computation for links. *

* For more discussion and examples, see Link Points. * * Elements other than the main {@link Shape} in the Link may act as decorations on the link, including arrowheads and labels. * You can control where they are located along the link route and how they are oriented. * Because these decorations may be any {@link GraphObject}, they are all properties of that class. * The properties include: * - {@link GraphObject.segmentIndex} * - {@link GraphObject.segmentFraction} * - {@link GraphObject.segmentOffset} * - {@link GraphObject.segmentOrientation} * * If you do not set the {@link GraphObject.segmentIndex} property, the object is positioned * to be at the middle of the link. *

* For more discussion and examples, see Link Labels. * * **GoJS** makes it easy to add arrowheads to your link template. * Just add a {@link Shape} with the appearance properties that you want, * and also set the {@link Shape.toArrow} or {@link Shape.fromArrow} property * to the name of the kind of arrowhead that you want. * Doing so automatically sets the "segment..." properties that are appropriate for the chosen arrowhead. * * More than one shape may automatically get the route geometry. * This is useful when you want to have multiple link shapes with different thicknesses * to create a gradient effect across the path of the link or to produce parallel lines along the path. * Just set {@link GraphObject.isPanelMain} to true on each such {@link Shape}. * * If you want the user to be able to reconnect a link, using the {@link RelinkingTool}, * you need to set one or both of {@link relinkableFrom} and {@link relinkableTo} to true. * The {@link RelinkingTool} shows a {@link RelinkingTool.fromHandleArchetype} and/or a * {@link RelinkingTool.toHandleArchetype} when the link is selected. * Such a relink handle can be dragged by the user to start a relinking operation. * * If you want the user to be able to change the path of the link, using the {@link LinkReshapingTool}, * set {@link Part.reshapable} to true. * The {@link LinkReshapingTool} shows reshape handles that the user can drag to shift the position * of a point in the link's route. * The {@link LinkReshapingTool.handleArchetype} is copied for each reshape handle. * * Often if a Link is reshapable, you will want to save the route in the model so that it can be restored * upon load. To save the route automatically, add a TwoWay Binding on the {@link points} property: * `new go.Binding("points").makeTwoWay()`. {@link Model.toJson} will automatically * convert the {@link List} of {@link Point}s into an Array of numbers in the JSON representation, * if the property is named "points". * * If a Link is {@link Part.reshapable}, it is also possible to allow the user to add and remove segments * from the link's route by setting {@link resegmentable} to true. * This causes the {@link LinkReshapingTool} to add resegmenting handles at the midpoints of each segment. * The {@link LinkReshapingTool.midHandleArchetype} is copied for each resegment handle. * When the user drags such a resegmenting handle, a new segment is inserted into the route. * Also, when the user drags a reshape handle such that two adjacent segments end up in a straight line, * a segment is removed from the route. *

* For more discussion and examples, see Links, * Link Labels, and * Link Points. *

* To control what links a user may draw or reconnect, please read about * Validation. *

* To customize linking and relinking behavior, please read * Introduction to the Linking Tools * and Introduction to the RelinkingTool. * For customizing the reshaping of Links, * see Introduction to the LinkReshapingTool. * * Only Links that are in Diagrams can have connections with Nodes. * Templates should not be connected with Nodes, be members of Groups, or have any Adornments. */ export class Link extends Part { /** * Constructs an empty link that does not connect any nodes. * If you want the link to be seen, you must provide a {@link Shape} as an element * to be used as the visual path for the link. * * Usage example: * *```js * // Constructs a Link, sets properties on it, * // adds a data binding to it, * // and adds two Shapes to the Link: * const l = new go.Link({ * routing: go.Routing.Orthogonal * }) * .add( * new go.Shape({ strokeWidth: 2 }), * new go.Shape({ toArrow: "Standard" }) * ); * ``` * * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * @deprecated See {@link Routing.Normal}. */ static readonly Normal = Routing.Normal; /** * @deprecated See {@link Routing.Orthogonal}. */ static readonly Orthogonal = Routing.Orthogonal; /** * @deprecated See {@link Routing.AvoidsNodes}. */ static readonly AvoidsNodes = Routing.AvoidsNodes; /** * @deprecated See {@link Curve.None}, {@link LinkAdjusting.None}, {@link Orientation.None}. */ static readonly None = 0; /** * @deprecated See {@link Curve.Bezier}. */ static readonly Bezier = Curve.Bezier; /** * @deprecated See {@link Curve.JumpGap}. */ static readonly JumpGap = Curve.JumpGap; /** * @deprecated See {@link Curve.JumpOver}. */ static readonly JumpOver = Curve.JumpOver; /** * @deprecated See {@link LinkAdjusting.End}. */ static readonly End = LinkAdjusting.End; /** * @deprecated See {@link LinkAdjusting.Scale}. */ static readonly Scale = LinkAdjusting.Scale; /** * @deprecated See {@link LinkAdjusting.Stretch}. */ static readonly Stretch = LinkAdjusting.Stretch; /** * @deprecated See {@link Orientation.Along}. */ static readonly OrientAlong = Orientation.Along; /** * @deprecated See {@link Orientation.Plus90}. */ static readonly OrientPlus90 = Orientation.Plus90; /** * @deprecated See {@link Orientation.Minus90}. */ static readonly OrientMinus90 = Orientation.Minus90; /** * @deprecated See {@link Orientation.Opposite}. */ static readonly OrientOpposite = Orientation.Opposite; /** * @deprecated See {@link Orientation.Upright}. */ static readonly OrientUpright = Orientation.Upright; /** * @deprecated See {@link Orientation.Plus90Upright}. */ static readonly OrientPlus90Upright = Orientation.Plus90Upright; /** * @deprecated See {@link Orientation.Minus90Upright}. */ static readonly OrientMinus90Upright = Orientation.Minus90Upright; /** * @deprecated See {@link Orientation.Upright45}. */ static readonly OrientUpright45 = Orientation.Upright45; /** * Gets or sets the {@link Node} that this link comes from. * The {@link fromPortId} specifies which port the link comes from. * The default value is null -- this link is not coming from any node. * * A template should not be connected with any node. */ get fromNode(): Node | null; set fromNode(value: Node | null); /** * Gets or sets the identifier of the port that this link comes from. * The default value is the empty string. */ get fromPortId(): string; set fromPortId(value: string); /** * This read-only property returns a {@link GraphObject} that is the "from" port that this link is connected from. * The {@link fromNode} provides the node that the link is coming from. * The {@link fromPortId} provides the identifier for which port this link is coming from; * you can set that property in order to change the value of this property. * This method may return null. */ get fromPort(): GraphObject | null; /** * Gets or sets the function that is called after this Link changes which Node or port it connects from. * The first argument will be this Link. * The second argument will be the old GraphObject port. * The third argument will be the new GraphObject port. * * If the value is a function, that function must not modify which nodes or links this link connects with. * The "from" node and/or port has already been changed -- trying to change it again may produce undefined behavior. * * The default value is null -- no function is called. */ get fromPortChanged(): ((thisLink: Link, oldPort: GraphObject | null, newPort: GraphObject | null) => void) | null; set fromPortChanged(value: ((thisLink: Link, oldPort: GraphObject | null, newPort: GraphObject | null) => void) | null); /** * Gets or sets the {@link Node} that this link goes to. * The {@link toPortId} specifies which port the link goes to. * The default value is null -- this link is not going to any node. * * A template should not be connected with any node. */ get toNode(): Node | null; set toNode(value: Node | null); /** * Gets or sets the identifier of the port that this link goes to. * The default value is the empty string. */ get toPortId(): string; set toPortId(value: string); /** * This read-only property returns a {@link GraphObject} that is the "to" port that this link is connected to. * The {@link toNode} provides the node that the link is going to. * The {@link toPortId} provides the identifier for which port this link is going to; * you can set that property in order to change the value of this property. * This method may return null. */ get toPort(): GraphObject | null; /** * Gets or sets the function that is called after this Link changes which Node or port it connects to. * The first argument will be this Link. * The second argument will be the old GraphObject port. * The third argument will be the new GraphObject port. * * If the value is a function, that function must not modify which nodes or links this link connects with. * The "to" node and/or port has already been changed -- trying to change it again may produce undefined behavior. * * The default value is null -- no function is called. */ get toPortChanged(): ((thisLink: Link, oldPort: GraphObject | null, newPort: GraphObject | null) => void) | null; set toPortChanged(value: ((thisLink: Link, oldPort: GraphObject | null, newPort: GraphObject | null) => void) | null); /** * Gets or sets where this link should connect at the {@link fromPort}. * The default value is {@link Spot.Default}, meaning that the value * actually comes from the {@link GraphObject.fromSpot} property of the {@link fromPort}. * * This property is set by some layouts, if {@link ForceDirectedLayout.setsPortSpots} or * {@link LayeredDigraphLayout.setsPortSpots} or {@link TreeLayout.setsPortSpot} or * {@link TreeLayout.setsChildPortSpot} is true. * * For examples of how to use this property, see Link Connection Points. * @see {@link toSpot} * @see {@link GraphObject.fromSpot} * @see {@link computeSpot} */ get fromSpot(): Spot; set fromSpot(value: Spot); /** * Gets or sets the length of the first segment, when the computed "from spot" at the {@link fromPort} is not {@link Spot.None}. * The default value is NaN, meaning that the value * actually comes from the {@link GraphObject.fromEndSegmentLength} property of the {@link fromPort}. * This value also limits how short the {@link fromShortLength} may be drawn. * * For examples of how to use this property, see Link Connection Points. * @see {@link toEndSegmentLength} * @see {@link computeEndSegmentLength} * @see {@link GraphObject.fromEndSegmentLength} * @see {@link fromShortLength} */ get fromEndSegmentLength(): number; set fromEndSegmentLength(value: number); /** * Gets or sets how far the end segment stops short of the actual port. * Positive values are limited by the {@link fromEndSegmentLength} or {@link GraphObject.fromEndSegmentLength}. * Negative values cause the link to extend into the port. * The default value is NaN -- the value actually comes from the * {@link GraphObject.fromShortLength} property of the {@link fromPort}. * * For examples of how to use this property, see Link Connection Points. * If you want to move an arrowhead away from the start of the link route, * set the arrowhead Shape's {@link GraphObject.segmentOffset}. * @see {@link toShortLength} * @see {@link GraphObject.fromShortLength} * @see {@link fromEndSegmentLength} */ get fromShortLength(): number; set fromShortLength(value: number); /** * Gets or sets where this link should connect at the {@link toPort}. * The default value is {@link Spot.Default}, meaning that the value * actually comes from the {@link GraphObject.toSpot} property of the {@link toPort}. * * This property is set by some layouts, if {@link ForceDirectedLayout.setsPortSpots} or * {@link LayeredDigraphLayout.setsPortSpots} or {@link TreeLayout.setsPortSpot} or * {@link TreeLayout.setsChildPortSpot} is true. * * For examples of how to use this property, see Link Connection Points. * @see {@link fromSpot} * @see {@link GraphObject.toSpot} * @see {@link computeSpot} */ get toSpot(): Spot; set toSpot(value: Spot); /** * Gets or sets the length of the last segment. * The default value is NaN, meaning that the value * actually comes from the {@link GraphObject.toEndSegmentLength} property of the {@link toPort}. * This value also limits how short the {@link toShortLength} may be drawn. * * For examples of how to use this property, see Link Connection Points. * @see {@link fromEndSegmentLength} * @see {@link computeEndSegmentLength} * @see {@link GraphObject.toEndSegmentLength} * @see {@link toShortLength} */ get toEndSegmentLength(): number; set toEndSegmentLength(value: number); /** * Gets or sets how far the end segment stops short of the actual port. * Positive values are limited by the {@link toEndSegmentLength} or {@link GraphObject.toEndSegmentLength}. * Negative values cause the link to extend into the port. * The default value is NaN -- the value actually comes from the * {@link GraphObject.toShortLength} property of the {@link toPort}. * * For examples of how to use this property, see Link Connection Points. * If you want to move an arrowhead away from the end of the link route, * set the arrowhead Shape's {@link GraphObject.segmentOffset}. * @see {@link fromShortLength} * @see {@link GraphObject.toShortLength} * @see {@link toEndSegmentLength} */ get toShortLength(): number; set toShortLength(value: number); /** * Given a {@link Node}, return the node at the other end of this link. * @param node * @returns This may return the same node, if the link is reflexive. */ getOtherNode(node: Node): Node | null; /** * Given a {@link GraphObject} that is a "port", return the port at the other end of this link. * @param port * @returns This may return the same object, if the link is reflexive. */ getOtherPort(port: GraphObject): GraphObject | null; /** * This read-only property is true when this Link has any label Nodes, {@link Node}s that are owned by this Link * and are arranged along its path in the same manner as elements of the Link Panel. * @see {@link labelNodes} */ get isLabeledLink(): boolean; /** * This read-only property returns an iterator over the {@link Node}s that act as labels on this Link. * Setting {@link Node.labeledLink} to refer to this Link * will add that {@link Node} to this collection. * * Do not confuse these {@link Node}s with the {@link GraphObject}s that * are part of this {@link Link} {@link Panel}. * Those objects can also be used as "labels", but not as objects to which * there can be link connections, because those panel elements cannot be {@link Node}s. * Those panel objects can be used for other purposes too, such as arrowheads. * * A template should not have any label nodes. * @see {@link isLabeledLink} */ get labelNodes(): Iterator; /** * Move this link to a new position. * This also shifts all of the Points in the route accordingly. * This also moves any {@link labelNodes}. * @param newpos - a new {@link Point} in document coordinates. * @param useLocation - true if you want to set the {@link location} instead of the position. False by default. */ move(newpos: Point, useLocation?: boolean): void; /** * Gets or sets whether the user may reconnect an existing link at the "from" end. * This affects the behavior of the {@link RelinkingTool}. * * The initial value is false. */ get relinkableFrom(): boolean; set relinkableFrom(value: boolean); /** * Gets or sets whether the user may reconnect an existing link at the "to" end. * This affects the behavior of the {@link RelinkingTool}. * * The initial value is false. */ get relinkableTo(): boolean; set relinkableTo(value: boolean); /** * This predicate returns true if {@link relinkableFrom} is true, * if the layer's {@link Layer.allowRelink} is true, and * if the diagram's {@link Diagram.allowRelink} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may relink the From end of this link. */ canRelinkFrom(): boolean; /** * This predicate returns true if {@link relinkableTo} is true, * if the layer's {@link Layer.allowRelink} is true, and * if the diagram's {@link Diagram.allowRelink} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may relink the To end of this link. */ canRelinkTo(): boolean; /** * Gets or sets whether the user may change the number of segments in this Link, * if the link has straight segments. * This affects the behavior of the {@link LinkReshapingTool} when {@link curve} is not {@link Curve.Bezier}. * * The initial value is false. */ get resegmentable(): boolean; set resegmentable(value: boolean); /** * Gets or sets whether this Link is part of the tree for tree operations * such as {@link Node.findTreeChildrenNodes} or {@link Node.collapseTree}. * * The initial value is true. */ get isTreeLink(): boolean; set isTreeLink(value: boolean); /** * This read-only property returns the main {@link Shape} representing the path of this Link. * * The value depends on there being an element in this Link that is * a {@link Shape} and that has {@link GraphObject.isPanelMain} set to true. * This shape is what displays the stroke going from one node to another node. * * This path shape's geometry is automatically generated based on the {@link points} * of this link's route, depending on other properties such as {@link curve}. * Note that the points are in document coordinates, but the path's {@link Shape.geometry} * will have points that are in local Shape coordinates. * This Shape's {@link GraphObject.scale} should be one and {@link GraphObject.angle} should be zero. * * If there is no Shape with {@link GraphObject.isPanelMain} set to true, * the Link will use the first Shape for its path. */ get path(): Shape | null; /** * This read-only property returns the bounds of the link geometry in document coordinates. * @since 2.2 */ get routeBounds(): Rect; /** * This read-only property returns the point at the middle of the path, in document coordinates. */ get midPoint(): Point; /** * This read-only property returns the angle of the path at the {@link midPoint}. */ get midAngle(): number; /** * Gets or sets the {@link List} of {@link Point}s in the route. * All of the Points must be {@link Point.isReal} -- no NaN or infinite values -- * and all of the points are in document coordinates. * Although this list may be replaced by setting this property, * one must not modify the contents of the List directly. * * The setter also accepts an Array of alternating X,Y point values `[1, 2, 3, 4, 5, 6]`, * or an Array of Objects each of which has (lowercase) 'x' and 'y' properties that are numbers * `[{"x":1,"y":2}, {"x":3,"y":4}, {"x":5,"y":6}]`. * * Ownership of the {@link List} and all of its {@link Point}s that is provided to the setter * is transferred to this Link. */ get points(): List; set points(value: List); /** * This read-only property returns the number of points in the route. */ get pointsCount(): number; /** * Gets a particular point of the route. * @param i - int The zero-based index of the desired point. * @returns in document coordinates */ getPoint(i: number): Point; /** * Sets a particular point of the route; this may only be called within an override of {@link computePoints}. * @param i - int The zero-based index of the desired point. * @param p - The new point in document coordinates, which should not have infinite or NaN coordinate values, and which must not be modified afterwards. * @see {@link getPoint} * @see {@link insertPoint} * @see {@link addPoint} * @see {@link removePoint} */ setPoint(i: number, p: Point): void; /** * (undocumented) * Sets a particular point of the route; this may only be called within an override of {@link computePoints}. * @param i - int The zero-based index of the desired point. * @param x - The new X, which should not be infinite or NaN, in document coordinates. * @param y - The new Y, which should not be infinite or NaN, in document coordinates. */ setPointAt(i: number, x: number, y: number): void; /** * Insert a point at a particular position in the route, without replacing an existing point; this may only be called within an override of {@link computePoints}. * @param i - int The zero-based index of the new point. * @param p - The new point in document coordinates, which should not have infinite or NaN coordinate values, and which must not be modified afterwards. * @see {@link getPoint} * @see {@link setPoint} * @see {@link addPoint} * @see {@link removePoint} */ insertPoint(i: number, p: Point): void; /** * (undocumented) * Insert a point at a particular position in the route, without replacing an existing point; this may only be called within an override of {@link computePoints}. * @param i - int The zero-based index of the new point. * @param x - The new X, which should not be infinite or NaN, in document coordinates. * @param y - The new Y, which should not be infinite or NaN, in document coordinates. */ insertPointAt(i: number, x: number, y: number): void; /** * Add a point at the end of the route; this may only be called within an override of {@link computePoints}. * @param p - The new point in document coordinates, which should not have infinite or NaN coordinate values, and which must not be modified afterwards. * @see {@link getPoint} * @see {@link setPoint} * @see {@link insertPoint} * @see {@link removePoint} */ addPoint(p: Point): void; /** * (undocumented) * Add a point at the end of the route; this may only be called within an override of {@link computePoints}. * @param x - The new X, which should not be infinite or NaN, in document coordinates. * @param y - The new Y, which should not be infinite or NaN, in document coordinates. */ addPointAt(x: number, y: number): void; /** * Remove a particular point from the route; this may only be called within an override of {@link computePoints}. * @param i - int The zero-based index of the point to extract. * @see {@link getPoint} * @see {@link setPoint} * @see {@link insertPoint} * @see {@link addPoint} * @see {@link clearPoints} */ removePoint(i: number): void; /** * Remove all of the points from this link's route; this may only be called within an override of {@link computePoints}. * @see {@link getPoint} * @see {@link setPoint} * @see {@link insertPoint} * @see {@link addPoint} * @see {@link removePoint} */ clearPoints(): void; /** * (undocumented) * Allow calls to {@link setPoint}, {@link addPoint}, {@link insertPoint}, * {@link removePoint}, and {@link clearPoints}. * You must call {@link commitRoute} when you are done modifying the route. */ startRoute(): void; /** * (undocumented) * Call this method after a call to {@link startRoute} and calls to methods that modify the route. */ commitRoute(): void; /** * (undocumented) * Call this method instead of {@link commitRoute} if you need to cancel changes to the route. */ rollbackRoute(): void; /** * Declare that the route (the {@link points}) of this Link need to be recomputed soon. * This causes {@link updateRoute} to be called, which will call {@link computePoints} * to perform the actual determination of the route. */ invalidateRoute(): void; /** @hidden Undocumented */ get suspendsRouting(): boolean; /** @hidden Undocumented */ set suspendsRouting(value: boolean); /** * (undocumented) */ get defaultFromPoint(): Point | null; set defaultFromPoint(value: Point | null); /** * (undocumented) */ get defaultToPoint(): Point | null; set defaultToPoint(value: Point | null); /** * This method recomputes the route if the route is invalid, * to make sure the {@link points} are up-to-date. * This method calls {@link computePoints} in order to calculate a new route. * * The route may become invalid if either connected node is moved, * or if various properties are modified, such as {@link routing}. * Such changes will call {@link invalidateRoute}. * * It is unusual for you to have to call this method. */ updateRoute(): void; /** * The code that constructs a new route by modifying the {@link points}. * It is only called by {@link updateRoute}, when needed. * All route points are always in document coordinates. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * Overrides of this method may call a number of "protected" methods in order to build the route: * {@link clearPoints}, {@link addPoint}, {@link insertPoint}, {@link removePoint}, {@link setPoint}. * Overrides of this method must not set {@link points}. * * Other methods that are commonly called and may be overridden are: * {@link computeEndSegmentLength}, {@link computeSpot}, {@link computeOtherPoint}, * {@link computeCurve}, {@link computeCurviness}, {@link hasCurviness}, * {@link computeThickness}, * {@link makeGeometry}. * @virtual * @returns true if it computed a route of points */ computePoints(): boolean; /** * Compute the intersection point in document coordinates for the edge of a particular port GraphObject, given a point, * when no particular spot or side has been specified. * @virtual * @param node * @param port - the {@link GraphObject} representing a port on the node. * @param focus - the point in document coordinates to/from which the link should point, * normally the center of the port. * @param p - often this point is far away from the node, to give a general direction, * particularly an orthogonal one. * @param from - true if the link is coming out of the port; false if going to the port. * @param result - an optional Point that is modified and returned; otherwise it allocates and returns a new Point * @returns the point in document coordinates of the intersection point on the edge of the port. */ getLinkPointFromPoint(node: Node | null, port: GraphObject | null, focus: Point, p: Point, from: boolean, result?: Point): Point; /** * Compute the point on a node/port in document coordinates at which the route of a link should end. * @virtual * @param node * @param port - the {@link GraphObject} representing a port on the node. * @param spot - a {@link Spot} value describing where the link should connect. * @param from - true if the link is coming out of the port; false if going to the port. * @param ortho - whether the link should have orthogonal segments. * @param othernode - the node at the other end of the link. * @param otherport - the {@link GraphObject} port at the other end of the link. * @param result - an optional Point that is modified and returned; otherwise it allocates and returns a new Point * @returns in document coordinates. */ getLinkPoint(node: Node | null, port: GraphObject, spot: Spot, from: boolean, ortho: boolean, othernode: Node | null, otherport: GraphObject, result?: Point): Point; /** * Compute the direction in which a link should go from a given connection point. * @virtual * @param node * @param port - the {@link GraphObject} representing a port on the node. * @param linkpoint - the connection point, in document coordinates. * @param spot - a {@link Spot} value describing where the link should connect. * @param from - true if the link is coming out of the port; false if going to the port. * @param ortho - whether the link should have orthogonal segments. * @param othernode - the node at the other end of the link. * @param otherport - the {@link GraphObject} port at the other end of the link. * @returns the absolute angle, in degrees. */ getLinkDirection(node: Node | null, port: GraphObject | null, linkpoint: Point, spot: Spot, from: boolean, ortho: boolean, othernode: Node | null, otherport: GraphObject | null): number; /** * Get the length of the end segment in document coordinates, typically a short distance, in document units. * For spot values that are {@link Spot.isSide}, this returns a computed value. * Depending on the `from` argument, this will return {@link fromEndSegmentLength} or {@link toEndSegmentLength}. * If the value is `NaN`, this will return the {@link fromPort}'s {@link GraphObject.fromEndSegmentLength} * or the {@link toPort}'s {@link GraphObject.toEndSegmentLength}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param node * @param port - the {@link GraphObject} representing a port on the node. * @param spot - a {@link Spot} value describing where the link should connect. * @param from - true if the link is coming out of the port; false if going to the port. * @returns a distance in document coordinates; must be a real number, not NaN or infinity. */ computeEndSegmentLength(node: Node | null, port: GraphObject | null, spot: Spot, from: boolean): number; /** * Get the {@link Spot} that describes how the end of the link should connect with the port. * Depending on the `from` argument, this will return {@link fromSpot} or {@link toSpot}. * If the value is {@link Spot.isDefault}, this will return the {@link fromPort}'s {@link GraphObject.fromSpot} * or the {@link toPort}'s {@link GraphObject.toSpot}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param from * @param port * @returns must not be {@link Spot.Default}, but may be {@link Spot.None} */ computeSpot(from: boolean, port?: GraphObject | null): Spot; /** * Find the approximate point of the other end of the link in document coordinates. * This is useful when computing the connection point when there is no specific spot, to have an idea of which general direction the link should be going. * By default this will return the center of the other port. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param othernode * @param otherport * @returns approximately where the other end of this link might end, in document coordinates */ computeOtherPoint(othernode: Node, otherport: GraphObject): Point; /** * (undocumented) * @virtual * @param from * @returns must be a real number, not NaN or infinity. */ protected computeShortLength(from: boolean): number; /** * This read-only property is true if {@link routing} is a value that implies that the points * of the route should be orthogonal, such that each point shares a common X or a common Y value * with the immediately previous and next points. * This property is completely dependent on the {@link routing} property. * Values of {@link Routing.Orthogonal} and {@link Routing.AvoidsNodes} causes this property to be true. * * The points in the route might not actually form an orthogonal route, but when the route is computed * the intent is to maintain orthogonality. */ get isOrthogonal(): boolean; /** * (undocumented) * This read-only property is true when the routing tries to be smart about not overlapping other parts. */ get isAvoiding(): boolean; /** * Returns the {@link curve}, unless this link is supposed to pretend to be curved, as with reflexive links. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ computeCurve(): Curve; /** * (undocumented) * Returns the {@link corner}, if it's a non-negative number, or else 10. * @virtual * @returns must be a real number, not NaN or infinity */ protected computeCorner(): number; /** * (undocumented) * Returns the first label that should be at the "middle" of the link, if there is any such label. * Elements that have .isPanelMain === true are ignored, including the {@link path}. * Elements that have a {@link GraphObject.segmentIndex} set are ignored, such as arrowheads. * If there are no label objects within the Link Panel, consider any {@link labelNodes} * whose segmentIndex has not been set. * This could be overridden to return a different label than the first one, or to always return null. * @virtual */ findMidLabel(): GraphObject | null; /** * Returns the expected spacing between this link and others that connect this link's fromPort and toPort. * This calls {@link computeThickness} and also takes any "mid label"'s breadth into account. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns must be a real number, not NaN or infinity * @see {@link computeCurviness} */ computeSpacing(): number; /** * (undocumented) * Sort the Links between two ports and invalidate their routes. * Only one of the Links in the bundle will get this method called -- it is undetermined which Link is chosen. * * By default does not change the order of the links, but does invalidate all routes if REROUTE is true. * This method must not add Links to or remove Links from the argument Array, but may re-order the Links in the Array. * @virtual * @param links * @param reroute */ arrangeBundledLinks(links: Array, reroute: boolean): void; /** * Returns the {@link curviness}, if it's a number, * or else a computed value based on how many links connect this pair of nodes/ports, * by calling {@link computeSpacing} on each link. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns must be a real number, not NaN or infinity * @see {@link computeSpacing} */ computeCurviness(): number; /** * Returns the thickness of this link. * By default it uses the strokeWidth of the main element, assuming it's a Shape. * This is called by {@link computeSpacing}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns a non-negative real number */ computeThickness(): number; /** * Returns true if an extra or a different point is needed based on {@link curviness}. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ hasCurviness(): boolean; /** * (undocumented) * This method is called by {@link computePoints} when the link is orthogonal * and at least one port has a link spot that is not {@link Spot.isNoSpot}. * * {@link computePoints} is responsible for adding the first two * and the last two points of the stroke, including the startFrom and endTo values. * This method is responsible for adding any additional points in the middle of the stroke. * This method calls {@link computeMidOrthoPosition} to determine the * distance of the middle segment between the two ports. * It also tries to avoid the source node and the destination node. * When the {@link routing} property is not Normal, * this method uses another, more computationally expensive, * method for determining the proper path of the link, which may have many segments. * @virtual * @param startFrom - this {@link Point} will already have been added to the stroke by {@link computePoints} before calling this method. * @param fromDir - Normally 0, 90, 180, or 270 degrees. * @param endTo - {@link computePoints} will add this {@link Point} after calling this method. * @param toDir - Normally 0, 90, 180, or 270 degrees. * @param fromnode - the {@link Node} that the link is coming from. * @param tonode - the {@link Node} that the link is going to. */ addOrthoPoints(startFrom: Point, fromDir: number, endTo: Point, toDir: number, fromnode: Node, tonode: Node): void; /** * (undocumented) * This method is called by {@link addOrthoPoints} to determine the distance * of the middle segment between the two ports. * @virtual * @param fromX - The first point's X coordinate. * @param fromY - The first point's Y coordinate. * @param toX - The last point's X coordinate. * @param toY - The last point's Y coordinate. * @param vertical - Whether the mid-position is along the vertical axis or horizontal axis. * @returns must be a real number, not NaN or infinity */ protected computeMidOrthoPosition(fromX: number, fromY: number, toX: number, toY: number, vertical: boolean): number; /** * Find the index of the segment that is closest to a given point. * This assumes the route only has straight line segments. * It ignores any jump-overs or jump-gaps. * @param p - the Point, in document coordinates. * @returns int the index of the segment, from zero to the number of points minus 2. */ findClosestSegment(p: Point): number; /** * This read-only property returns the {@link Geometry} that is used by the {@link path}, the link {@link Shape} based on the route points. * * This geometry is automatically generated using the route points and other properties * such as the {@link curve}. * The points of the Geometry are in local coordinates, whereas the {@link points} of the link route are in document coordinates. * * More than one {@link Shape} may share this geometry as its {@link Shape.geometry}, * if there is more than one shape element in the Link with {@link GraphObject.isPanelMain} set to true. */ get geometry(): Geometry; /** * Produce a {@link Geometry} given the points of this route, * depending on the value of {@link curve} and {@link corner} and perhaps other properties. * The points of the Geometry are in local coordinates, whereas the {@link points} of the link route are in document coordinates. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ makeGeometry(): Geometry; /** * (undocumented) */ get firstPickIndex(): number; /** * (undocumented) */ get lastPickIndex(): number; /** * Gets or sets how the route is computed, including whether it uses the points of its old route to determine the new route. * The value must be one of {@link LinkAdjusting.None|None}, {@link LinkAdjusting.End|End}, {@link LinkAdjusting.Scale|Scale}, or {@link LinkAdjusting.Stretch|Stretch}. * * The default value is {@link LinkAdjusting.None|None} -- the route is completely recalculated each time. * @see {@link computeAdjusting} */ get adjusting(): LinkAdjusting; set adjusting(value: LinkAdjusting); /** * Returns the {@link adjusting} value, unless this Link's Diagram is animating and the routing is AvoidsNodes -- * then it will return {@link LinkAdjusting.End|End} * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * @virtual * @since 2.1 * @see {@link adjusting} */ computeAdjusting(): LinkAdjusting; /** * Gets or sets how rounded the corners are for adjacent line segments when the {@link curve} * is {@link Curve.None|None}, {@link Curve.JumpGap|JumpGap}, or {@link Curve.JumpOver|JumpOver} and * the two line segments are orthogonal to each other. * * The default value is zero -- there is no curve at a corner. */ get corner(): number; set corner(value: number); /** * Gets or sets the way the path is generated from the route's points. * The value must be one of {@link Curve.None|None}, {@link Curve.Bezier|Bezier}, {@link Curve.JumpGap|JumpGap}, or {@link Curve.JumpOver|JumpOver}. * * Setting this property to {@link Curve.JumpOver|JumpOver} or {@link Curve.JumpGap|JumpGap} requires the Diagram to do * considerable computation when calculating Link routes. Consider not using * a Jump... value with Diagrams that contain large numbers of Links * if you are targeting slow devices. * * The default value is {@link Curve.None|None} -- each link segment is a straight line. * @see {@link computeCurve} */ get curve(): Curve; set curve(value: Curve); /** * Gets or sets how far the control points are offset when the {@link curve} is {@link Curve.Bezier|Bezier} * or when there are multiple links between the same two ports. * * The default value is NaN -- the actual curviness is computed based on how many links connect the same pair of ports. * @see {@link computeCurviness} */ get curviness(): number; set curviness(value: number); /** * Gets or sets whether the link's path tries to avoid other nodes. * The value must be one of {@link Routing.Normal|Normal}, {@link Routing.Orthogonal|Orthogonal}, or {@link Routing.AvoidsNodes|AvoidsNodes}. * * Setting this property to {@link Routing.AvoidsNodes|AvoidsNodes} requires the Diagram to do * considerable computation when calculating Link routes. Consider not using * the {@link Routing.AvoidsNodes|AvoidsNodes} with Diagrams that contain large numbers of Nodes and Links * if you are targeting slow devices. * When using {@link Routing.AvoidsNodes|AvoidsNodes}, dragging performance can be improved by setting {@link DraggingTool.isComplexRoutingRealtime} to false. * * The default value is {@link Routing.Normal|Normal} -- the route is primarily a single straight segment, * with possible short end segments when connecting with ports that have a "spot" value * as the {@link fromSpot} or {@link GraphObject.fromSpot} or {@link toSpot} or {@link GraphObject.toSpot}. */ get routing(): Routing; set routing(value: Routing); /** * Gets or sets how far the control points are from the points of the route * when {@link routing} is {@link Routing.Orthogonal|Orthogonal} and {@link curve} is {@link Curve.Bezier|Bezier}. * * The default value is 0.5. * Values of this property typically fall in the range of 0.0 to 1.0. * A value of 0.0 indicates that the control points of the curve are at the end points, * which will result in straight line segments. * A value of 1.0 indicates that the control points are one-third of the link's * length away from the end point along the direction of the link, * and the same distance away in a perpendicular direction. * The distance scales linearly with the value of this property, * even with negative values and values greater than 1.0. */ get smoothness(): number; set smoothness(value: number); /** * This read-only property returns the Links's Model data key if it is in a Diagram and is backed by Model data. * Otherwise this returns undefined. * * If the link data is in a GraphLinksModel, the {@link GraphLinksModel.linkKeyProperty} must not be an empty string. * @see {@link GraphLinksModel.getKeyForLinkData} */ get key(): Key; } /** * Undocumented */ export class PositionArray { constructor(cellsize: Size); get bounds(): Rect; get cellWidth(): number; set cellWidth(value: number); get cellHeight(): number; set cellHeight(value: number); /** * Undocumented * @param x - in document coordinates. * @param y * @param w * @param h */ isUnoccupied(x: number, y: number, w: number, h: number): boolean; /** * (undocumented) * @param minx * @param maxx * @param y * @param h * @returns int */ maxAvoidsLinksSpaceH(minx: number, maxx: number, y: number, h: number): number; /** * (undocumented) * @param miny * @param maxy * @param x * @param w * @returns int */ maxAvoidsLinksSpaceV(miny: number, maxy: number, x: number, w: number): number; } /** * A Group is a {@link Node} that can contain a subgraph of {@link Node}s and {@link Link}s, * which are members of the group. *

* For more discussion, see Introduction to Groups. * See samples that make use of Groups in the samples index. * * Although you can create a Group and {@link Diagram.add} it to a Diagram, this does not update the Model. * It is more common to create a group by adding a node data object to the model * by calling {@link Model.addNodeData}. For example: * ```js * myDiagram.startTransaction("make new group"); * myDiagram.model.addNodeData({ key: "Omega", isGroup: true }); * myDiagram.commitTransaction("make new group"); * ``` * * This will cause a Group to be created (copying the template found in {@link Diagram.groupTemplateMap}), * added to the Diagram in some {@link Layer} (based on {@link Part.layerName}), and bound to the group data * (resulting in {@link Panel.data} referring to that group data object). * Note that the JavaScript object includes setting `isGroup` to true, * to indicate that the object represents a Group rather than a regular Node or simple Part. * * The member Parts of a Group, which you can access as the {@link memberParts} collection, * belong to the group but are not in the visual tree of the group. * All {@link Part}s are directly in {@link Layer}s -- they cannot be inside a {@link Panel}. * This allows group member parts to be in layers different from the group's layer. * * You can change the membership of a {@link Node} or a simple {@link Part} in a Group by setting * its {@link Part.containingGroup} property. * This is done automatically for you by the diagram if you initialize the `group` property on the node data * in the model to be the key of the containing group node data. * Thus you should do something like: * ```js * myDiagram.startTransaction("add new member"); * myDiagram.model.addNodeData({ group: someExistingGroupKey, ... }); * myDiagram.commitTransaction("add new member"); * ``` * * where you would make sure the node data object included all of the properties you need. * You can also change the relationship dynamically by calling {@link GraphLinksModel.setGroupKeyForNodeData}. * * The membership of {@link Link}s is computed automatically for you by the diagram based on the membership of * the connected {@link Node}s. * For example, if the {@link Link.fromNode} is a top-level node but the {@link Link.toNode} is a member of a group, * the link is a top-level link. * If the two connected nodes both belong to the same group, the link is a member of that group. * If the two connected nodes belong to different groups, the link belongs to the common container group, if there is any. * Note that if a link connects a member of a group with the group itself, the link is a member of that group. * * All of the group-member relationships effectively form a tree structure. * These properties and methods are useful in navigating these relationships: * - {@link Part.containingGroup} * - {@link Part.isTopLevel} * - {@link Part.findTopLevelPart} * - {@link Part.findSubGraphLevel} * - {@link Part.findCommonContainingGroup} * - {@link memberParts} * - {@link findSubGraphParts} * - {@link findExternalLinksConnected} * - {@link findExternalNodesConnected} * * As the membership of a group changes, you may want to update the appearance of the group. * You can set the {@link memberAdded} and {@link memberRemoved} properties to be functions that are called. * These functions must not modify any membership relationships -- these function properties just exist to update the appearance of the Group. * * You can control whether certain Nodes are added to a Group by {@link CommandHandler.groupSelection} or * {@link addMembers} or {@link CommandHandler.addTopLevelParts} by affecting the result of {@link CommandHandler.isValidMember}, * which is responsible for deciding whether it is OK to add a Node to a Group or to remove a Node from a Group to be a top-level node. * You can override that predicate on CommandHandler, but it is easier to set the {@link memberValidation} or * {@link CommandHandler.memberValidation} functional property. *

* For a more general discussion of validation, see Introduction to Validation. * * The area occupied by the subgraph is represented in the group's visual tree by a {@link Placeholder}. * As the group {@link placeholder} grows and shrinks based on the sizes and positions of the member nodes and links, * the group will grow and shrink accordingly. * The placeholder is always the {@link Part.locationObject}, * although you may specify any {@link Spot} as the {@link Part.locationSpot}. * A Group need not have a placeholder, but it may have at most one. * * A group has its own {@link layout} property that is used to position the member nodes and route the member links. * * The Group class also supports the notion of expanding and collapsing the subgraph, * causing the member nodes and links to be shown or hidden. * Principally this is a matter of setting {@link isSubGraphExpanded}. * Changes to this property will result in calls to {@link collapseSubGraph} or {@link expandSubGraph}, as appropriate. * * If you want to change the appearance of the group you can do so in a function that you assign to * the {@link subGraphExpandedChanged} property. * This function must not modify any member relationships or expand or collapse any groups -- the functional property just exists * to update the appearance of the Group. *

* For more discussion and examples, see SubGraphs. * * If you want the user to be able to create a Group out of the currently * selected Parts using the {@link CommandHandler.groupSelection} command, * you need to first set the {@link CommandHandler.archetypeGroupData} property * to a data object with `isGroup` set to true. * If you want the user to be able to ungroup a Group, * using the {@link CommandHandler.ungroupSelection} command, * you need to set {@link ungroupable} to true. *

* For more discussion and examples, see Groups, * SubGraphs, and * Sized Groups. * * Only Groups that are in Diagrams can have member Parts or connections via Links. * Templates should not be connected with Links, be labels of Links, be members of Groups, have any member Parts, or have any Adornments. */ export class Group extends Node { /** * Constructs an empty Group with no visual elements and no member parts; * typically a Group will have some visual elements surrounding a {@link Placeholder}. * * The panel type must be a {@link PanelLayout}, such as {@link Panel.Position}). * The string value such as "Auto" may also be used. * * Usage example: * *```js * // Constructs a Group, sets properties on it, * // adds a data binding to it, * // and adds two GraphObjects to the Group: * const g = new go.Group("Auto", { * margin: 5, * background: "red" * }) * .add( * new go.Shape("RoundedRectangle"), * new go.TextBlock("Some Text") * ); * ``` * * @param type - a string or PanelLayout, such as "Horizontal", {@link Panel.Vertical}. * If not supplied, the default Panel type is "Position". * @param init - Optional initialization properties. */ constructor(type?: PanelLayout | string, init?: Partial); /** * Constructs an empty Panel. Default type is {@link Panel.Position}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * This read-only property returns a {@link Placeholder} that this group may contain in its visual tree. * The value may be null if there is no Placeholder in the visual tree of this Group. * * There may be at most one Placeholder in a Group. * The Placeholder determines the {@link Part.location} for the Group, when it is visible, * and even when {@link isSubGraphExpanded} is false. * When there is a Placeholder, the {@link Part.locationObjectName} is ignored and the * {@link Part.locationObject} will be this Placeholder. */ get placeholder(): Placeholder | null; /** * Gets or sets whether the size of the area of the {@link Group}'s {@link placeholder} * should remain the same during a {@link DraggingTool} move until a drop occurs. * Groups within temporary layers (such as new Groups during a drag-copy) are unaffected by this property. * * In other words, when the value is true, re-computing the bounds of the * members is suspended until a drop occurs, at which time the border is recomputed, * perhaps not including some members that had been dragged out and reparented. * The initial value is false. */ get computesBoundsAfterDrag(): boolean; set computesBoundsAfterDrag(value: boolean); /** * Gets or sets whether a {@link placeholder}'s bounds includes the bounds of member Links. * The default value is true. * If this is false, only non-Link member Parts are used to compute the Placeholder's bounds in document coordinates. */ get computesBoundsIncludingLinks(): boolean; set computesBoundsIncludingLinks(value: boolean); /** * Gets or sets whether a {@link placeholder}'s bounds includes the previous Group.location. * The default value is false. */ get computesBoundsIncludingLocation(): boolean; set computesBoundsIncludingLocation(value: boolean); /** * Gets or sets whether drag-and-drop events may be bubbled up to this Group if not handled by member Parts. * The default value is false -- each Node or Link that is a member of the Group needs to define * its own {@link GraphObject.mouseDragEnter}, {@link GraphObject.mouseDragLeave}, and {@link GraphObject.mouseDrop} * event handlers if you want dragging/dropping on a member part to act as if the user were acting on the group. * * This is currently restricted to only call the mouseDragEnter, mouseDragLeave, and mouseDrop event handlers * defined on the whole Group, not on any element inside the Group's visual tree. */ get handlesDragDropForMembers(): boolean; set handlesDragDropForMembers(value: boolean); /** @hidden */ get avoidableMembers(): boolean; /** @hidden */ set avoidableMembers(value: boolean); /** * This read-only property returns an iterator over the member {@link Part}s of this Group. * Setting {@link Part.containingGroup} to refer to this Group * will add that part to this collection. * The Parts can be {@link Node}s, {@link Link}s, {@link Group}s, or simple {@link Part}s. * * A template should not have any member parts. */ get memberParts(): Iterator; /** * Gets or sets the {@link Layout} used to position all of the immediate member nodes and links in this group. * By default this property is an instance of {@link Layout} -- no special layout is used, which just makes * sure each member node has a valid location. * * A group layout must not be shared with any {@link Diagram.layout}. */ get layout(): Layout | null; set layout(value: Layout | null); /** * Gets or sets the function that is called after a member {@link Part} has been added to this Group. * It is typically used to modify the appearance of the group. * The first argument will be this Group. * The second argument will be a Part, typically a Node, but may be a simple Part or a Link. * * If the value is a function, that function must not modify any membership relationships. * The member Part has already been added -- trying to remove it or adding or removing another member or the Group itself may produce undefined behavior. * * The default value is null -- no function is called. */ get memberAdded(): ((thisGroup: Group, newPart: Part) => void) | null; set memberAdded(value: ((thisGroup: Group, newPart: Part) => void) | null); /** * Gets or sets the function that is called after a member {@link Part} has been removed from this Group. * It is typically used to modify the appearance of the group. * The first argument will be this Group. * The second argument will be a Part, typically a Node, but may be a simple Part or a Link. * * If the value is a function, that function must not modify any membership relationships. * The member Part has already been removed -- trying to add it or adding or removing another member or the Group itself may produce undefined behavior. * * The default value is null -- no function is called. */ get memberRemoved(): ((thisGroup: Group, oldPart: Part) => void) | null; set memberRemoved(value: ((thisGroup: Group, oldPart: Part) => void) | null); /** * Gets or sets the predicate that determines whether or not a Part may become a member of this group. * If this is non-null, the predicate is called in addition to any {@link CommandHandler.memberValidation} predicate. * * The default predicate is null, which is equivalent to simply returning true. * The first argument will be this Group. * The second argument will be a Part, typically a Node, but will not be a Link or an Adornment. * * The function, if supplied, must not have any side-effects. */ get memberValidation(): ((thisGroup: Group | null, part: Part) => boolean) | null; set memberValidation(value: ((thisGroup: Group | null, part: Part) => boolean) | null); /** * See if the given collection of {@link Part}s contains non-Links all for which * {@link CommandHandler.isValidMember} returns true. * * The CommandHandler predicate will use {@link CommandHandler.memberValidation} * and {@link memberValidation}, if either or both are defined. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @param coll * @returns true. */ canAddMembers(coll: Iterable): boolean; /** * Add the {@link Part}s in the given collection as members of this Group * for those Parts for which {@link CommandHandler.isValidMember} returns true. * If the check argument to this method is not supplied or false, * this will set {@link Part.containingGroup} on each part unconditionally, not calling {@link CommandHandler.isValidMember}. * * The CommandHandler predicate will use {@link CommandHandler.memberValidation} * and {@link memberValidation}, if either or both are defined. * * At this time there is no "removeMembers" method. * If you want to make a collection of Parts to be top-level parts, not members of any Group but still in the Diagram, call {@link CommandHandler.addTopLevelParts}. * If you want to remove a collection of Parts not only from a Group but from the whole Diagram, call {@link Diagram.removeParts}. * @virtual * @param coll * @param check - whether to call {@link CommandHandler.isValidMember} to confirm that it is valid to add the Part to be a member of this Group. * @returns true if all non-Links were added to this Group; false if some Parts or Nodes were not able to be added. */ addMembers(coll: Iterable, check?: boolean): boolean; /** * Gets or sets whether the user may ungroup this group. * The initial value is false. * @see {@link canUngroup} */ get ungroupable(): boolean; set ungroupable(value: boolean); /** * This predicate returns true if {@link ungroupable} is true, * if the layer's {@link Layer.allowUngroup} is true, and * if the diagram's {@link Diagram.allowUngroup} is true. * * This does not check {@link Diagram.isReadOnly} or {@link Model.isReadOnly}, * but commands and tools should check those properties. * @virtual * @returns true if the user may ungroup this object. */ canUngroup(): boolean; /** * Returns an iterator over all of the {@link Link}s that connect with this group or any node contained by this group, * in either direction, but that are not internal to this group. * * Links that are contained by this group (even in nested groups) are not included in the result collection. * @see {@link Node.findLinksConnected} */ findExternalLinksConnected(): Iterator; /** * Returns an iterator over all of the {@link Node}s that are connected with this group or any node contained by this group, * by a link in either direction, but that are not internal to this group. * * Nodes that are contained by this group (even in nested groups) are not included in the result collection. * However this group itself might be in the results if there is a reflexive link connected to this group. * @see {@link Node.findNodesConnected} */ findExternalNodesConnected(): Iterator; /** * Return a collection of {@link Part}s that are all of the nodes and links * that are members of this group, including inside nested groups and label nodes, * but excluding this group itself. * * For member nodes that are {@link Group}s, this will include its members recursively. * * If you want only the immediate members of this group, use the {@link memberParts} property. * * If you want to find the collection of Nodes and Links that are in the subtree of a given {@link Node}, use {@link Node.findTreeParts}. */ findSubGraphParts(): Set; /** * Hide each of the member nodes and links of this group, * and recursively collapse any member groups. * This changes the value of {@link Part.isVisible} of the whole subgraph and the parts owned by * those member nodes and links. * However, this group's visibility is unchanged. * * This sets {@link isSubGraphExpanded} to false on this group and on all of the nested {@link Group}s. * For those nested {@link Group}s that were expanded, * {@link wasSubGraphExpanded} is set to true. * * This method does not perform a transaction or start any animation. * * To collapse trees made of {@link Node}s and {@link Link}s, use {@link Node.collapseTree}. */ collapseSubGraph(): void; /** * Show each member node and link, * and perhaps recursively expand nested subgraphs. * This may change the value of {@link Part.isVisible} of the whole subgraph and the parts owned by * those member nodes and links. * However, this group's visibility is unchanged. * * This sets {@link isSubGraphExpanded} to true on this group and on all of the nested {@link Group}s. * This will expand a nested group only if its {@link wasSubGraphExpanded} property was true. * * This method does not perform a transaction or start any animation. * * To expand trees made of {@link Node}s and {@link Link}s, use {@link Node.expandTree}. */ expandSubGraph(): void; /** * Gets or sets whether the subgraph contained by this group is expanded. * Changing this property's value will call {@link collapseSubGraph} or {@link expandSubGraph}, * and also will call the value of {@link subGraphExpandedChanged} if it is a function. * * The initial value is true -- this group's member parts are shown. * * There is an analogous property for expanded/collapsed trees of {@link Node}s and {@link Link}s: {@link Node.isTreeExpanded}. */ get isSubGraphExpanded(): boolean; set isSubGraphExpanded(value: boolean); /** * Gets or sets whether the subgraph starting at this group * had been collapsed by a call to {@link expandSubGraph} on the containing {@link Group}. * The initial value is false. * @see {@link isSubGraphExpanded} */ get wasSubGraphExpanded(): boolean; set wasSubGraphExpanded(value: boolean); /** * Gets or sets the function that is called when {@link isSubGraphExpanded} has changed value. * The argument to that function will be this Group. * * If the value is a function, that function must not expand or collapse any groups. * The Group has already been expanded or collapsed -- trying to change it again may produce undefined behavior. * * The default value is null -- no function is called. */ get subGraphExpandedChanged(): ((thisGroup: Group) => void) | null; set subGraphExpandedChanged(value: ((thisGroup: Group) => void) | null); /** * Move this Group and all of its member parts, recursively. * * This method does not perform a transaction or start any animation. * @param newpos - a new {@link Point} in document coordinates. * @param useLocation - true if you want to set the {@link location} instead of the position. False by default. */ move(newpos: Point, useLocation?: boolean): void; } /** * If a Placeholder is in the visual tree of a {@link Group}, it represents the area of all of the member {@link Part}s of that Group. * If a Placeholder is in the visual tree of an {@link Adornment}, it represents the area of the {@link Adornment.adornedObject}. * Unlike other GraphObjects, the Placeholder measures itself based on these criteria, and not on its own {@link desiredSize} or {@link scale}. * It will set its own natural bounds and scale, and in the case of Groups will set the Group's location. * * It can only be used in the visual tree of a Group node or an Adornment. * There can be at most one Placeholder in a Group or an Adornment. * * See the documentation for {@link Group} and {@link Adornment} for descriptions of the Placeholder roles in each. */ export class Placeholder extends GraphObject { /** * This normally does not need any initialization, * except for maybe setting {@link padding}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * (undocumented) * This is only called when the Placeholder is inside a {@link Group}. * Normally this just returns the result of {@link computeMemberBounds} expanded by the {@link padding}. * However, if {@link Group.computesBoundsAfterDrag} is true, * and if the {@link Diagram.currentTool} is the {@link DraggingTool}, * and if this {@link Group} is not being dragged, * this method returns the last value of {@link computeBorder} before dragging began. * @virtual * @param result * @returns in document coordinates. */ protected computeBorder(result: Rect): Rect; /** * (undocumented) * Compute the union of the Bounds of this Placeholder's parent's Group.memberParts. * If there are no members, this returns a {@link Rect} with Width and Height of zero * and an X and Y that are this panel's original location in document coordinates. * This is only called when the Placeholder is inside a {@link Group}. * @virtual * @param result * @returns in document coordinates. */ protected computeMemberBounds(result: Rect): Rect; /** * Gets or sets the padding around the members of the {@link Group} or around the {@link Adornment.adornedObject} {@link GraphObject}. * The initial value is a {@link Margin} of zero on all sides. */ get padding(): MarginLike; set padding(value: MarginLike); } /** * This is the base class for all of the predefined diagram layout implementations. * They only arrange {@link Part}s (primarily {@link Node}s and {@link Link}s) in a {@link Diagram}, * not to {@link GraphObject}s in {@link Panel}s (i.e. panel layout). * * The layout classes include {@link TreeLayout}, {@link ForceDirectedLayout}, * {@link LayeredDigraphLayout}, {@link CircularLayout}, and {@link GridLayout}. * This base class is not abstract -- in fact an instance of this base class is the default * value for {@link Diagram.layout} and for {@link Group.layout}. * * An instance of a Layout class will be the value of {@link Diagram.layout}. * That layout positions the graph of top-level nodes and links. * Nodes and links that belong to a {@link Group} are laid out by that group's {@link Group.layout}. * The Diagram will automatically perform all nested group layouts before laying out the whole diagram. * * If you have position information for all of the nodes when you load a model, * you will typically have data bound the {@link Part.location} to some property on your node data. * In order to avoid an initial layout causing those saved node positions to be discarded, * you can either not set the {@link Diagram.layout} to a predefined layout or you can * set {@link isInitial} to false. * * Because performing layouts can be expensive in space and time, automatic layouts * are performed only on "invalid" layouts, and only well after a layout has been invalidated. * This state is held by the {@link isValidLayout} property. * Many standard operations, such as adding or removing nodes or links, will cause * the layout that is responsible for positioning those nodes or routing those links * to be invalidated. * Such invalidation is performed by calling {@link invalidateLayout}, * which not only clears the {@link isValidLayout} state but also requests that the diagram * do an automatic layout soon. * You can avoid such invalidations by setting {@link isOngoing} to false. * * Layouts will ignore parts that have {@link Part.isLayoutPositioned} set to false * or parts that are not {@link GraphObject.visible}. * Layouts will also ignore parts that are in layers that are {@link Layer.isTemporary}. * * Various operations on {@link Part}s will cause the responsible Layout to be invalidated. * This includes adding or removing parts, changing their visibility, and changing their size. * You can disable such automatic layout invalidations by setting {@link Part.layoutConditions} * to the combination of Part flags named "Layout..." that you want. * * But operations on parts are not the only way in which layouts become invalidated. * Setting most properties on the layouts, thereby changing their behavior, will invalidate that layout. * Replacing the {@link Diagram.layout} or {@link Group.layout} will automatically invalidate the new layout. * If {@link isViewportSized} is true, when a diagram's {@link Diagram.viewportBounds} changes size, * the {@link Diagram.layout} is invalidated. * (This is normally only true for {@link GridLayout}s when its {@link GridLayout.wrappingWidth} is `NaN`. * Most layouts do not care about the size of the viewport.) * * You can also explicitly call {@link Diagram.layoutDiagram}, which can invalidate all layouts and * then perform them all. * But we recommend that you avoid doing so, to allow the normal updating process perform layouts as needed. * * If an automatic layout is the first time that a layout has been performed for the model, * the diagram first raises the {@link DiagramEvent} named "InitialLayoutCompleted". * Whenever a Diagram finishes an automatic layout, it raises the DiagramEvent named "LayoutCompleted". * * It is also possible to call {@link doLayout} explicitly, but this is uncommon and only used with * instances of Layout that are not the {@link Diagram.layout} or {@link Group.layout}. * It should only be needed when you want to layout a collection of nodes and links that is not * the normal graph of top-level parts of a Diagram or a subgraph of a Group. * * More complicated layouts make use of a separate {@link LayoutNetwork}, consisting of {@link LayoutVertex}es and {@link LayoutEdge}s, * that normally holds a graph that is isomorphic to the graph consisting of {@link Node}s and {@link Link}s in the {@link Diagram} or {@link Group}. * The implementation of {@link doLayout} will call {@link makeNetwork} and remember the result as the {@link network}. * {@link makeNetwork} will call {@link createNetwork} and initialize it by adding new instances of LayoutVertexes and LayoutEdges * corresponding to the given collection of Nodes and Links. * * When {@link doLayout} is finished with its work it will call {@link updateParts}, which will call {@link commitLayout} * to set new node locations and route links. It then normally discards the {@link network}. * * The LayoutVertex and LayoutEdge instances allow the layout to work with more information about each Node and Link without * actually modifying those Nodes and Links until {@link commitLayout} is called to actually set the Node locations and route the Links. * The use of a LayoutNetwork also allows the Layout to work with a graph that is not isomorphic to the given collection of Nodes and Links. * This is useful when needing to use dummy vertexes and/or edges to achieve certain layout behaviors, * or when one wants to ignore certain vertexes or edges, without actually modifying or adding or removing the diagram's nodes or links. * * An instance of this base class provides a rudimentary default layout that will position * all of the parts that have no position (i.e. the {@link Part.location} is (NaN,NaN). * Parts that already have a position are ignored. * This primitive layout class does not make use of a {@link LayoutNetwork} because * it ignores all links. * * To implement your own custom layouts, you can inherit from either this class or * from one of the other predefined layout classes. * If you inherit from this base class, you will want to override the {@link doLayout} method. * You can call the {@link Part.move} method to re-position a part, including whole groups. * Please read the Introduction page on Extensions for how to override methods and how to call a base method. * @category Layout */ export class Layout { /** * Create a minimal layout that only positions {@link Node}s that do not have a location. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Copies properties from this object to the given object, which is of the same class. * This is called by {@link copy} and should be overridden for each class that adds properties. * There are examples of such overrides in the samples. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param copy */ protected cloneProtected(copy: this): void; /** * Creates a copy of this Layout and returns it. * When a {@link Group} is copied that has a {@link Group.layout}, the {@link Layout} must also be copied. * This calls {@link cloneProtected} on a newly constructed Layout. * @virtual */ copy(): this; /** * Gets the {@link Diagram} that owns this layout, if it is the value of {@link Diagram.layout}. * * If this property and {@link group} are non-null, the Group should be in this Diagram. * @see {@link group} * @readonly */ get diagram(): Diagram | null; set diagram(value: Diagram | null); /** * Gets the {@link Group} that uses this layout, if it is the value of a group's {@link Group.layout}. * * If this property is set to a Group, the {@link diagram} is automatically set to be the Group's Diagram. * @see {@link diagram} * @readonly */ get group(): Group | null; set group(value: Group | null); /** * Gets or sets whether this layout can be invalidated by {@link invalidateLayout}. * Set this to false to prevent actions such as adding or removing Parts from invalidating this layout. * The default value is true. * Setting this property does not invalidate this layout. * * If you set both {@link isInitial} and {@link isOngoing} to false, * there will be no automatic layout invalidation, because {@link invalidateLayout} * will not set {@link isValidLayout} to false. * To get your nodes to appear, you will need to explicitly set or data-bind their {@link Part.location} * or {@link GraphObject.position} to real Point values, because automatic layout will not assign any positions. * * Another way of controlling when layouts are invalidated is by setting * {@link Part.isLayoutPositioned} or {@link Part.layoutConditions}. */ get isOngoing(): boolean; set isOngoing(value: boolean); /** * Gets or sets whether this layout is performed on an initial layout. * The default value is true. * Setting this property to false causes {@link isValidLayout} to be set to true * so that the diagram does not perform this layout. * * If you set both {@link isInitial} and {@link isOngoing} to false, * there will be no automatic layout invalidation, because {@link invalidateLayout} * will not set {@link isValidLayout} to false. * To get your nodes to appear, you will need to explicitly set or data-bind their {@link Part.location} * or {@link GraphObject.position} to real Point values, because automatic layout will not assign any positions. * * Another way of controlling when layouts are invalidated is by setting * {@link Part.isLayoutPositioned} or {@link Part.layoutConditions}. */ get isInitial(): boolean; set isInitial(value: boolean); /** * Gets or sets whether this layout depends on the {@link Diagram.viewportBounds}'s size. * If set to true, the layout will invalidate when the Diagram's viewport changes size. * This only applies to diagram layouts, not to group layouts, * and only when {@link Diagram.autoScale} is set to {@link AutoScale.None}. * * The default value is false. * Setting this property to true will invalidate this layout. * * It is possible that a viewport-sized layout will trigger the Diagram to require scrollbars, * which modifies the {@link Diagram.viewportBounds}, which will in turn trigger another layout. * This is uncommon, but possible with {@link GridLayout} if the results require a vertical scrollbar, * and that vertical scrollbar shrinks the viewport width enough that a grid column can no longer fit. * When designing custom layouts, one should be careful that this behavior does not result in an infinite loop. */ get isViewportSized(): boolean; set isViewportSized(value: boolean); /** * Gets or sets whether this layout routes {@link Link}s. * The default value is true. * When false, this layout will not explicitly set the {@link Link.points}, * and the default routing of each individual Link will take place after the Nodes are moved by {@link commitLayout}. * Setting this property does not invalidate this layout. * * Some layouts ignore links, in which case this property is ignored. */ get isRouting(): boolean; set isRouting(value: boolean); /** * Gets or sets whether this layout be performed in real-time, before the end of a transaction. * All layouts that are invalidated will be performed at the end of a transaction. * The default value is null. * A null value is treated as true for a {@link Diagram.layout} but false for a {@link Group.layout}. * Setting this property does not invalidate this layout. */ get isRealtime(): boolean | null; set isRealtime(value: boolean | null); /** * Gets or sets whether this layout needs to be performed again (if false). * Instead of setting this property directly, it is normal to set it to false by calling {@link invalidateLayout}, * since that also requests performing a layout in the near future. */ get isValidLayout(): boolean; set isValidLayout(value: boolean); /** * If {@link isOngoing} is true and if an initial layout has not yet been performed, * set the {@link isValidLayout} property to false, and ask to perform another layout in the near future. * If {@link isInitial} is true, this layout is invalidated only when the {@link Diagram.model} is replaced, * not under the normal circumstances such as when parts are added or removed or * due to other calls to {@link Layout.invalidateLayout}. * * If you set both {@link isInitial} and {@link isOngoing} to false, * there will be no automatic layout invalidation, because this method * will not set {@link isValidLayout} to false. * However you can still set {@link isValidLayout} explicitly. * * This is typically called when a layout property value has changed, * or when a Part is added or removed or changes visibility, if {@link Part.layoutConditions} includes the pertinent flags. */ invalidateLayout(): void; /** * Gets or sets the {@link LayoutNetwork} used by this Layout, if any. * The default value is null. * Setting this property does not invalidate this layout. * Not all kinds of layout make use of a {@link LayoutNetwork}. * Call {@link createNetwork} or {@link makeNetwork} to create a network. */ get network(): LayoutNetwork | null; set network(value: LayoutNetwork | null); /** * Create a new {@link LayoutNetwork} of {@link LayoutVertex}es and {@link LayoutEdge}s. * This may be overridden in Layout subclasses to create instances of subclasses of * {@link LayoutNetwork}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @returns a new {@link LayoutNetwork}. */ createNetwork(): LayoutNetwork; /** * Create and initialize a {@link LayoutNetwork} with the given nodes and links. * This should be called by {@link doLayout} when this layout uses a {@link network}. * This method calls {@link createNetwork} to allocate the network. * This may be overridden in Layout subclasses to customize the initialization. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. * @returns normally the value of a call to {@link createNetwork} initialized by vertexes and edges corresponding to the *coll* argument. */ makeNetwork(coll: Diagram | Group | Iterable): LayoutNetwork; /** * When using a {@link LayoutNetwork}, update the "physical" node positionings and link routings. * This should be called by {@link doLayout} when this layout uses a {@link network}. * This calls {@link commitLayout} to actually set {@link Node} positions and route {@link Link}s. * This performs the changes within a transaction. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ updateParts(): void; /** * When using a {@link LayoutNetwork}, commit changes to the diagram * by setting {@link Node} positions and by routing the {@link Link}s. * This is called by {@link updateParts} within a transaction. * * You should not call this method -- it is a "protected virtual" method. * This may be overridden by subclasses of Layout. * By default this method is implemented as follows: * ```js * protected commitLayout() { * if (this.network === null) return; * const vit = this.network.vertexes.iterator; * while (vit.next()) { * const vert = vit.value; * vert.commit(); * } * if (this.isRouting) { * const eit = this.network.edges.iterator; * while (eit.next()) { * const edge = eit.value; * edge.commit(); * } * } * } * ``` * * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitLayout(): void; /** * Position all of the nodes that do not have an assigned {@link Part.location} * in the manner of a simple rectangular array. * The default implementation ignores all {@link Group}s and {@link Link}s; * many subclasses of {@link Layout} ignore all instances of {@link Part}s * that are not {@link Node}s or {@link Link}s. * * You can override this method to do whatever node positioning and link routing * that you wish. * * When the layout makes use of a {@link LayoutNetwork}, * this method should call {@link makeNetwork} and {@link updateParts}. * The {@link updateParts} method will call {@link commitLayout} within a transaction. * The outline of such an override should be like: * ```js * public doLayout(coll) { * if (this.network === null) this.network = this.makeNetwork(coll); * // assign LayoutVertex.bounds to all vertexes in the network: * const vit = this.network.vertexes.iterator; * while (vit.next()) { * const v = vit.value; * v.centerX = ... * v.centerY = ... * } * this.updateParts(); * this.network = null; * } * ``` * Override {@link commitLayout} to actually position nodes and route links. * * When the layout does not make use of a {@link LayoutNetwork}, * this method should make direct changes to {@link Node}s and {@link Link}s * within a transaction, and it should call {@link collectParts} on the argument *coll* in order * to get the proper set of Nodes and Links to work on. * Examples are provided in the Extensions directory. * * If this Layout belongs to a Diagram, the argument must be either the same Diagram or must denote Parts that belong to the Diagram. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ doLayout(coll: Diagram | Group | Iterable): void; /** * This method is called by layouts to determine the size and initial position of the nodes that it is laying out. * Normally this just returns the part's {@link GraphObject.actualBounds}. * However, if {@link boundsComputation} has been set to a function, that function will be called * in order to return the bounds of the given Part in document coordinates that the layout should pretend it has. * @virtual * @param part - the Part being laid out * @param rect - an optional Rect that will be modified and returned * @returns a Rect in document coordinates * @since 2.0 */ getLayoutBounds(part: Part, rect?: Rect): Rect; /** * Gets or sets a function that determines the initial size and position in document coordinates of a LayoutVertex corresponding to a Node. * This function is called by {@link getLayoutBounds}. * The default value for this property is null, in which case the {@link GraphObject.actualBounds} of the Node is used. * Setting this property to a new value invalidates this layout. * * The non-null value must be a function that takes 3 arguments. * The first argument will be the Part whose bounds the Layout should use. * The second argument will be this Layout. * The third argument will be a Rect that must be modified and returned * The return value must be in document coordinates. You may find it convenient to call {@link GraphObject.getDocumentBounds} * to get the bounds in document coordinates of an object within the node. * @since 2.0 */ get boundsComputation(): ((part: Part, lay: Layout, rect: Rect) => Rect) | null; set boundsComputation(value: ((part: Part, lay: Layout, rect: Rect) => Rect) | null); /** * A convenient way of converting the Diagram|Group|Iterable argument to doLayout to an actual collection of eligible Parts. * The resulting Set will not include any Nodes or Links for which {@link Part.canLayout} is false. * If the argument includes a Group for which {@link Group.layout} is null, the resulting Set * will include the member parts of that group rather than that group itself. * You will not need to call collectParts if you call {@link makeNetwork}, * because that method does effectively the same thing when building the {@link LayoutNetwork}. * * Typical usage: * ```js * public doLayout(coll) { * // COLL might be a Diagram or a Group or some Iterable * const it = this.collectParts(coll).iterator; * while (it.next()) { * const node = it.value; * if (node instanceof go.Node) { * . . . position the node . . . * } * } * } * ``` * @param coll */ protected collectParts(coll: Diagram | Group | Iterable): Set; /** * Gets or sets the top-left point for where the graph should be positioned when laid out. * The default value for this property is the Point(0, 0). * Setting this property to a new value invalidates this layout. * This property is likely to be set by many Layouts that belong to a Group when the layout is performed. */ get arrangementOrigin(): Point; set arrangementOrigin(value: Point); /** * Compute the desired value of {@link arrangementOrigin} if this Layout is being performed for a Group. * This is typically called near the beginning of the implementation of {@link doLayout}: * `this.arrangementOrigin = this.initialOrigin(this.arrangementOrigin);` * if the layout wants to respect the pre-layout location of the Group when deciding where to position its member nodes. * @virtual * @param origin */ protected initialOrigin(origin: Point): Point; } /** * This provides an abstract view of a diagram as a * network (graph) of vertexes and directed edges. * The network contains vertexes and edges corresponding to {@link Node}s and {@link Link}s. * * This class provides a framework for manipulating the * state of nodes and links without modifying the structure of the diagram. * Having a separate representation also permits adding or removing vertexes or edges * from the network so that the graph that is laid out is not isomorphic to the diagram's graph. * * For each kind of layout that uses a LayoutNetwork there is a subclass of {@link LayoutVertex} and a subclass of {@link LayoutEdge}: * - {@link CircularLayout}: {@link CircularVertex} and {@link CircularEdge} * - {@link ForceDirectedLayout}: {@link ForceDirectedVertex} and {@link ForceDirectedEdge} * - {@link LayeredDigraphLayout}: {@link LayeredDigraphVertex} and {@link LayeredDigraphEdge} * - {@link TreeLayout}: {@link TreeVertex} and {@link TreeEdge} * * Modifying a {@link LayoutNetwork} or a {@link LayoutVertex} or a {@link LayoutEdge} does not * invalidate the {@link Layout} or raise any changed events. * @category Layout */ export class LayoutNetwork { /** * This constructs an empty network. * It is commonplace to call {@link addParts} to build up the network * to have the same structure as a {@link Diagram}'s or {@link Group}'s nodes and links. */ constructor(layout: Layout); /** * Gets the {@link Layout} that uses this network * of {@link LayoutVertex}es and {@link LayoutEdge}s. * The default value is null. * It is set automatically for you when this setting {@link Layout.network}. * @readonly */ get layout(): Layout; set layout(value: Layout); /** * Gets a collection of all of the {@link LayoutVertex}es in this network. * Do not modify this collection directly. * Instead, call {@link addVertex}, {@link deleteVertex}, {@link addNode}, or {@link deleteNode}. */ get vertexes(): Set; /** * Gets a collection of all of the {@link LayoutEdge}s in this network. * Do not modify this collection directly. * Instead, call {@link addEdge}, {@link deleteEdge}, {@link addLink}, or {@link deleteLink}. */ get edges(): Set; /** * Allocate a new instance of {@link LayoutVertex}. * This is overridden in LayoutNetwork subclasses to create instances of subclasses of {@link LayoutVertex}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ createVertex(): LayoutVertex; /** * Allocate a new instance of {@link LayoutEdge}. * This is overridden in LayoutNetwork subclasses to create instances of subclasses of {@link LayoutEdge}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ createEdge(): LayoutEdge; /** * Creates a network of {@link LayoutVertex}es and {@link LayoutEdge}s * corresponding to the given {@link Node}s and {@link Link}s. * This is usually more convenient than repeatedly calling {@link addNode} and {@link addLink}. * This method ignores all instances of {@link Part}s that are not Nodes or Links. * This will recurse through {@link Group}s that have no {@link Group.layout}. * @param parts - A collection of {@link Node}s or {@link Link}s. * @param toplevelonly - whether to skip Parts in the given collection that are contained by Groups; default is false * @param pred - optional predicate to apply to each Part -- * if it returns false do not include Vertex or Edge in the network; * default ignores link label nodes or links connecting with them */ addParts(parts: Iterable, toplevelonly?: boolean, pred?: ((a: Part) => boolean) | null): void; /** * Adds a {@link LayoutVertex} to the network. * @param vertex */ addVertex(vertex: LayoutVertex): void; /** * This convenience method makes sure there is a {@link LayoutVertex} * in this network corresponding to a {@link Node}. * @param node * @returns a vertex in this network. */ addNode(node: Node): LayoutVertex; /** * Removes a {@link LayoutVertex} from the network. * This function also deletes all edges to or from the vertex. * @param vertex */ deleteVertex(vertex: LayoutVertex): void; /** * This convenience method deletes any {@link LayoutVertex} * corresponding to a {@link Node}. * @param node */ deleteNode(node: Node): void; /** * Returns the {@link LayoutVertex} that was constructed for the {@link Node}. * @param node * @returns a vertex in this network, or null if no such vertex exists. */ findVertex(node: Node): LayoutVertex | null; /** * Adds a {@link LayoutEdge} to the network. * Although this method is provided for completeness, * {@link linkVertexes} provides a more efficient manner of linking * vertexes already in the network. * @param edge */ addEdge(edge: LayoutEdge): void; /** * This convenience method makes sure there is a {@link LayoutEdge} * in this network corresponding to a {@link Link}. * If {@link findEdge} returns null, this method creates a new {@link LayoutEdge}, * makes sure the {@link Link.fromNode} and {@link Link.toNode} have * corresponding {@link LayoutVertex}es in the network, and adds the edge itself * to the network. * @param link * @returns an edge in this network. */ addLink(link: Link): LayoutEdge; /** * Removes a {@link LayoutEdge} from the network. * @param edge */ deleteEdge(edge: LayoutEdge): void; /** * This convenience method deletes from this network any {@link LayoutEdge} * corresponding to a {@link Link}. * @param link */ deleteLink(link: Link): void; /** * Returns the {@link LayoutEdge} that was constructed for the {@link Link}. * @param link * @returns an edge in this network, or null if no such edge exists. */ findEdge(link: Link): LayoutEdge | null; /** * Links two vertexes already in the network and returns the created {@link LayoutEdge}. * @param fromVertex * @param toVertex * @param link * @returns an edge in this network, or null if both vertexes don't exist. */ linkVertexes(fromVertex: LayoutVertex | null, toVertex: LayoutVertex | null, link: Link | null): LayoutEdge | null; /** * Reverses the direction of a {@link LayoutEdge} in the network. * @param edge */ reverseEdge(edge: LayoutEdge): void; /** * Deletes all {@link LayoutEdge}s whose "to vertex" and "from vertex" are the same vertex. */ deleteSelfEdges(): void; /** * Deletes all vertexes and edges that have no {@link Part} associated with them. * @virtual */ deleteArtificialVertexes(): void; /** * Modify this network by splitting it up into separate subnetworks, * each of which has all of its vertexes connected to each other, but not * to any vertexes in any other subnetworks. * * This method will first delete from this network all artificial vertexes and * all edges that do not connect two different vertexes. * Afterwards, this original network may be empty or may contain all of the * singleton vertexes, each of which had no edges connecting it to any other vertexes. * @param clean - whether to delete artificial vertexes and edges, disconnected edges, and reflexive edges; default is true * @returns a collection of {@link LayoutNetwork}s, * sorted in order of decreasing vertex count. */ splitIntoSubNetworks(clean?: boolean): List; /** * Retrieve all of the {@link Node}s and {@link Link}s from the * {@link LayoutVertex}es and {@link LayoutEdge}s that are in this network. * @returns A collection of {@link Part}s. */ findAllParts(): Set; } /** * A vertex represents a {@link Node} in a {@link LayoutNetwork}, * along with its {@link bounds} and {@link focus} and collections of {@link LayoutEdge}s that come into and go out of the vertex. * The {@link node} property may be null for vertexes that represent "dummy" nodes, * when the layout wants to work with a network that is not isomorphic with the collection of Nodes and Links being laid out. * * This holds layout-specific data for the node. * For each kind of layout that uses a LayoutNetwork there is a subclass of {@link LayoutVertex} and a subclass of {@link LayoutEdge}: * - {@link CircularLayout}: {@link CircularVertex} and {@link CircularEdge} * - {@link ForceDirectedLayout}: {@link ForceDirectedVertex} and {@link ForceDirectedEdge} * - {@link LayeredDigraphLayout}: {@link LayeredDigraphVertex} and {@link LayeredDigraphEdge} * - {@link TreeLayout}: {@link TreeVertex} and {@link TreeEdge} * * Modifying a {@link LayoutNetwork} or a {@link LayoutVertex} or a {@link LayoutEdge} does not * invalidate the {@link Layout} or raise any changed events. * @category Layout */ export class LayoutVertex { /** * This constructs a vertex that does not know about any {@link Node}. */ constructor(network: LayoutNetwork); /** * Gets or sets the data object in the model that should be associated with this vertex, if any. * The value will be non-null if this vertex is virtualized, * not represented by a real {@link Node} in the {@link Diagram}. * Each data object should have a 'bounds' property that is a {@link Rect} * or any JavaScript Object with 'x', 'y', 'width', and 'height' properties that are real numbers, * and non-negative numbers for the width and the height. * Setting this data property will also set the {@link bounds} and {@link focus} properties. */ get data(): ObjectData | null; set data(value: ObjectData | null); /** * Gets or sets the {@link Node} associated with this vertex, if any. * The value may be null if this vertex is a "dummy" vertex, * not represented by a real {@link Node} in the {@link Diagram}. * * This property setter also sets the {@link bounds} and {@link focus} properties * according to the value of the Node's actualBounds and its {@link Part.locationObject}'s center point. */ get node(): Node | null; set node(value: Node | null); /** * Gets or sets the bounds of this vertex, in document coordinates. * Setting this property does not directly modify the position of any {@link Node}, * but it will modify the value of {@link centerX} and {@link centerY}, * as well as the subsidiary convenience properties {@link x}, {@link y}, {@link width}, and {@link height}. */ get bounds(): Rect; set bounds(value: Rect); /** * Gets or sets the offset of the {@link focusX} and {@link focusY} * from the {@link bounds} position. * Setting this property does not directly modify the position of any {@link Node}, * but it does affect the value of {@link centerX} and {@link centerY}. * * The "focus" is normally the center of the Node's {@link Part.locationObject}. */ get focus(): Point; set focus(value: Point); /** * Gets or sets the center {@link Point.x} of this vertex, in document coordinates. * This property depends on both {@link bounds} and {@link focus}. * Setting this property does not modify the position of any {@link Node}, * but it will modify the value of {@link bounds}. */ get centerX(): number; set centerX(value: number); /** * Gets or sets the center {@link Point.y} of this vertex, in document coordinates. * This property depends on both {@link bounds} and {@link focus}. * Setting this property does not modify the position of any {@link Node}, * but it will modify the value of {@link bounds}. */ get centerY(): number; set centerY(value: number); /** * Gets or sets the relative X position of the "center" point, the focus. */ get focusX(): number; set focusX(value: number); /** * Gets or sets the relative Y position of the "center" point, the focus. */ get focusY(): number; set focusY(value: number); /** * Gets or sets the left point of this vertex. */ get x(): number; set x(value: number); /** * Gets or sets the top point of this vertex. */ get y(): number; set y(value: number); /** * Gets or sets the width of this vertex. * This is always the horizontal distance reserved for the node. */ get width(): number; set width(value: number); /** * Gets or sets the height of this vertex. * This is always the vertical distance reserved for the node. */ get height(): number; set height(value: number); /** * Moves the {@link Node} corresponding to this vertex * so that its position is at the current {@link bounds} point. * * To make the most common cases look right, the Node's {@link Part.locationObject} * is centered. Thus iconic nodes will have the center of the icon be positioned * according to the center of this vertex, ignoring any labels. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ commit(): void; /** * Adds a {@link LayoutEdge} to the list of predecessors * (the edge will be coming into this vertex). * Calling this method does not modify the {@link LayoutEdge.toVertex} of the LayoutEdge. * @param edge */ addSourceEdge(edge: LayoutEdge): void; /** * Deletes a {@link LayoutEdge} from the list of predecessors * (the edge was coming into this vertex). * Calling this method does not modify the {@link LayoutEdge.toVertex} of the LayoutEdge. * @param edge */ deleteSourceEdge(edge: LayoutEdge): void; /** * Adds a {@link LayoutEdge} to the list of successors * (the edge will be going out from this vertex). * Calling this method does not modify the {@link LayoutEdge.fromVertex} of the LayoutEdge. * @param edge */ addDestinationEdge(edge: LayoutEdge): void; /** * Deletes a {@link LayoutEdge} from the list of successors * (the edge was going out from this vertex). * Calling this method does not modify the {@link LayoutEdge.fromVertex} of the LayoutEdge. * @param edge */ deleteDestinationEdge(edge: LayoutEdge): void; /** * Gets the {@link LayoutNetwork} that owns this vertex. * The default value is null. * It is set automatically for you in {@link LayoutNetwork.createVertex}. * @readonly */ get network(): LayoutNetwork; set network(value: LayoutNetwork); /** * This read-only property returns an iterator for all of the vertexes that are connected with edges coming into this vertex. * * Note that this is inefficient compared to iterating over the edges ({@link sourceEdges}) due to the need * to avoid duplicate vertexes if there happen to be multiple edges connecting with the same vertex. */ get sourceVertexes(): Iterator; /** * This read-only property returns an iterator for all of the vertexes that are connected with edges going out of this vertex. * * Note that this is inefficient compared to iterating over the edges ({@link destinationEdges}) due to the need * to avoid duplicate vertexes if there happen to be multiple edges connecting with the same vertex. */ get destinationVertexes(): Iterator; /** * This read-only property returns an iterator for all of the vertexes that are connected in either direction with this vertex. * * Note that this is inefficient compared to iterating over the edges ({@link sourceEdges} and {@link destinationEdges}) due to the need * to avoid duplicate vertexes if there happen to be multiple edges connecting with the same vertex. */ get vertexes(): Iterator; /** * This read-only property returns an iterator for all of the edges that come into this vertex. */ get sourceEdges(): Iterator; /** * This read-only property returns an iterator for all of the edges that go out of this vertex. */ get destinationEdges(): Iterator; /** * This read-only property returns an iterator for all of the edges that are connected with this vertex in either direction. * * Note that this is inefficient compared to iterating over the edges: {@link sourceEdges} and {@link destinationEdges}. */ get edges(): Iterator; /** * This read-only property returns the total number of edges that are connected with this vertex in either direction. */ get edgesCount(): number; /** * This static function is used to compare the {@link Part.text} values of the {@link node}s of * the argument {@link LayoutVertex}es. * This just does a simple case-sensitive string comparison. * Alternatively you may wish to use {@link LayoutVertex.smartComparer} or write your own comparison function. * @param m * @param n * @returns int -1, 0, or 1, depending on whether the comparison between M and N is less than, equal, or greater than. */ static standardComparer(m: LayoutVertex, n: LayoutVertex): number; /** * This static function is used to compare the {@link Part.text} values of the {@link node}s of * the argument {@link LayoutVertex}es. * If the text ends in a number, the values are compared as numbers rather than lexicographically. * Naturally this comparison is significantly slower than {@link LayoutVertex.standardComparer}. * @param m * @param n * @returns int -1, 0, or 1, depending on whether the comparison between M and N is less than, equal, or greater than. */ static smartComparer(m: LayoutVertex, n: LayoutVertex): number; } /** * An edge represents a Link in a {@link LayoutNetwork}, * along with its {@link fromVertex} and {@link toVertex}. * The {@link link} property may be null for edges that represent "dummy" links, * when the layout wants to work with a network that is not isomorphic with the collection of Nodes and Links being laid out. * * It holds layout-specific data for the link. * For each kind of layout that uses a LayoutNetwork there is a subclass of {@link LayoutVertex} and a subclass of {@link LayoutEdge}: * - {@link CircularLayout}: {@link CircularVertex} and {@link CircularEdge} * - {@link ForceDirectedLayout}: {@link ForceDirectedVertex} and {@link ForceDirectedEdge} * - {@link LayeredDigraphLayout}: {@link LayeredDigraphVertex} and {@link LayeredDigraphEdge} * - {@link TreeLayout}: {@link TreeVertex} and {@link TreeEdge} * * Modifying a {@link LayoutNetwork} or a {@link LayoutVertex} or a {@link LayoutEdge} does not * invalidate the {@link Layout} or raise any changed events. * @category Layout */ export class LayoutEdge { /** * This constructs an edge that does not know about any {@link Link}. */ constructor(network: LayoutNetwork); /** * Commits the route of this edge to the corresponding {@link Link}, if any. * By default this does nothing. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ commit(): void; /** * Returns the edge's vertex at the other of this edge from the given vertex. * @param v */ getOtherVertex(v: LayoutVertex): LayoutVertex | null; /** * Gets the {@link LayoutNetwork} that owns this edge. * The default value is null. * It is set automatically for you in {@link LayoutNetwork.createEdge}. * @readonly */ get network(): LayoutNetwork; set network(value: LayoutNetwork); /** * For virtualized layouts working on model data instead of a Link. */ get data(): ObjectData | null; set data(value: ObjectData | null); /** * Gets or sets the {@link Link} associated with this edge, if any. * The value may be null if this edge is a "dummy" edge, * not represented by a real {@link Link} in the {@link Diagram}. */ get link(): Link | null; set link(value: Link | null); /** * Gets or sets the {@link LayoutVertex} that this edge comes from. * Setting this property does not change any {@link LayoutVertex.destinationEdges} collection. */ get fromVertex(): LayoutVertex | null; set fromVertex(value: LayoutVertex | null); /** * Gets or sets the {@link LayoutVertex} that this edge goes to. * Setting this property does not change any {@link LayoutVertex.sourceEdges} collection. */ get toVertex(): LayoutVertex | null; set toVertex(value: LayoutVertex | null); } /** * This enumeration specifies whether to position each part by its location or by its position. * Used for {@link GridLayout.alignment}. * @since 3.0 * @category Layout */ export declare enum GridAlignment { /** * Position the top-left corner of each part at a grid point. */ Position = 0, /** * Position the part's {@link Part.location} at a grid point. */ Location = 1 } /** * This enumeration specifies how to fill each row. * Used for {@link GridLayout.arrangement}. * @since 3.0 * @category Layout */ export declare enum GridArrangement { /** * Fill each row from left to right. */ LeftToRight = 10, /** * Fill each row from right to left. */ RightToLeft = 11 } /** * This enumeration specifies whether to sort the children of a part, and in what order to position them. * Used for {@link GridLayout.sorting}. * * The default {@link GridLayout.comparer} does a case-insensitive comparison of the value of each node's {@link Part.text} property. * @since 3.0 * @category Layout */ export declare enum GridSorting { /** * Lay out each child in the order in which they were found. */ Forwards = 20, /** * Lay out each child in reverse order from which they were found. */ Reverse = 21, /** * Lay out each child according to the sort order given by {@link GridLayout.comparer}. */ Ascending = 22, /** * Lay out each child in reverse sort order given by {@link GridLayout.comparer}. */ Descending = 23 } /** * This simple layout places all of the Parts in a grid-like arrangement, ordered, spaced apart, * and wrapping as needed. It ignores any Links connecting the Nodes being laid out. * There are many samples that use GridLayout. * Every {@link Palette} uses a GridLayout by default. *

* If you want to experiment interactively with most of the properties, try the Grid Layout sample. * See samples that make use of GridLayout in the samples index. * * By default this layout will sort all of the Parts alphabetically * (comparing {@link Part.text} values, respecting case) * and position them left-to-right, separated by {@link spacing}`.width`, * until they do not fit in the current row. * At that time it starts a new row, separated from the previous row by {@link spacing}`.height`. * There is a uniform cell size equal to the maximum Part width (plus spacing width) * and the maximum part height (plus spacing height). * At least one part is placed in each row, even if the part by itself is wider than the wrapping width. * * You can specify values for the {@link cellSize} `width` and `height`. * If a part is wider than the cell size, it spans more than one cell in the row. * * When the value of {@link wrappingWidth} is set to `NaN`, as it is by default, * the value of {@link Layout.isViewportSized} will be set to true. * This causes the layout to be performed again automatically as the viewport changes size. * You can also specify a real number value for the {@link wrappingWidth}, * which will be used instead of the diagram's viewport width, to control when each row is considered "full". * * You can also set {@link wrappingColumn} to limit the number of items in each row. * By default {@link wrappingColumn} is `NaN`, meaning that there is no limit on the number of items in any one row. * Both the {@link wrappingWidth} and the {@link wrappingColumn} are respected when deciding when to wrap to the next row. * * This layout is sufficiently simple that it does not use a {@link LayoutNetwork}. * @category Layout */ export class GridLayout extends Layout { /** * Constructs a {@link GridLayout} with no {@link Layout.network} * and with no owning {@link Layout.diagram}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Assign the positions of the parts, ignoring any links. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ doLayout(coll: Diagram | Group | Iterable): void; /** * Gets or sets the width beyond which the layout will start a new row. * * The default is NaN, meaning to use the width of the diagram's panel's viewport. * Infinity is a common value to produce a single row of parts, unless limited by {@link wrappingColumn}. * The value must be positive or NaN. * * If the new value is NaN, {@link Layout.isViewportSized} will be set to true. * When {@link Diagram.initialAutoScale} or {@link Diagram.autoScale} are not None, * it is common to set {@link wrappingColumn} and {@link wrappingWidth} to large values -- * whatever seems reasonable given the number and size of the parts that will be laid out * and the size of the viewport. */ get wrappingWidth(): number; set wrappingWidth(value: number); /** * Gets or sets the maximum number of items that the layout will arrange in a single row. * * The default is NaN, meaning not to limit the number of columns. * 1 is a common value to produce a single column of parts. * The value must be positive or NaN. * * When {@link Diagram.initialAutoScale} or {@link Diagram.autoScale} are not None, * it is common to set {@link wrappingColumn} and {@link wrappingWidth} to large values -- * whatever seems reasonable given the number and size of the parts that will be laid out * and the size of the viewport. */ get wrappingColumn(): number; set wrappingColumn(value: number); /** * Gets or sets the minimum part size by which each part is positioned in the grid. * * The default value is NaN x NaN. * The units are in document coordinates. * * When the cell size is smaller than a part, the part will occupy more than one cell. * This allows parts to be positioned closer to each other, but then variations in part * sizes may cause them not to be aligned in perfect rows or columns. */ get cellSize(): Size; set cellSize(value: Size); /** * Gets or sets the minimum horizontal and vertical space between parts. * * The default value is 10 x 10. * The units are in document coordinates. */ get spacing(): Size; set spacing(value: Size); /** * Gets or sets whether the {@link Part.location} or the position should be used * to arrange each part. * * The default value is {@link GridAlignment.Location} -- the {@link Part.location}s will * be aligned in a grid. */ get alignment(): GridAlignment; set alignment(value: GridAlignment); /** * Gets or sets how to arrange the parts. * Must be a {@link GridArrangement} value. * * The default value is {@link GridArrangement.LeftToRight}. */ get arrangement(): GridArrangement; set arrangement(value: GridArrangement); /** * Gets or sets what order to place the parts. * Must be a {@link GridSorting} value. * * The default value is {@link GridSorting.Ascending}. */ get sorting(): GridSorting; set sorting(value: GridSorting); /** * Gets or sets the comparison function used to sort the parts. * * The default value is a case-insensitive alphabetic comparison * using the {@link Part.text} property of each part. * ```js * new go.GridLayout({ * sorting: go.GridSorting.Ascending, * comparer: (pa, pb) => { * const da = pa.data; * const db = pb.data; * if (da.someProperty < db.someProperty) return -1; * if (da.someProperty > db.someProperty) return 1; * return 0; * } * }) * ``` */ get comparer(): ((a: Part, b: Part) => number); set comparer(value: ((a: Part, b: Part) => number)); /** * @deprecated See {@link GridAlignment.Position}. */ static readonly Position = GridAlignment.Position; /** * @deprecated See {@link GridAlignment.Location}. */ static readonly Location = GridAlignment.Location; /** * @deprecated See {@link GridArrangement.LeftToRight}. */ static readonly LeftToRight = GridArrangement.LeftToRight; /** * @deprecated See {@link GridArrangement.RightToLeft}. */ static readonly RightToLeft = GridArrangement.RightToLeft; /** * @deprecated See {@link GridSorting.Forwards}. */ static readonly Forward = GridSorting.Forwards; /** * @deprecated See {@link GridSorting.Reverse}. */ static readonly Reverse = GridSorting.Reverse; /** * @deprecated See {@link GridSorting.Ascending}. */ static readonly Ascending = GridSorting.Ascending; /** * @deprecated See {@link GridSorting.Descending}. */ static readonly Descending = GridSorting.Descending; } /** * For bindings: A side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. */ export type TargetConversion = ((val: any, targetObj: any) => any) | null; /** * For bindings: The optional conversion function to convert property values back to data values. * Specifying this function modifies a binding to set its {@link Binding.mode} to be {@link BindingMode.TwoWay}. * If you want a two-way binding without a back-conversion function, specify `null` for a `BackConversion`. * If you do not want a two-way binding, omit any `BackConversion`. */ export type BackConversion = ((val: any, sourceData: any, model: Model) => any) | null; /** * This enumeration specifies in which direction bindings will be evaluated. * Used for {@link Binding.mode}. * @since 3.0 * @category Model */ export declare enum BindingMode { /** * Uses data source values and sets {@link GraphObject} properties. * Bindings are evaluated when {@link Panel.updateTargetBindings} is called. */ OneWay = 1, /** * Uses data source values and {@link GraphObject} properties and keeps them in sync. * When {@link Panel.updateTargetBindings} is called, the {@link GraphObject} properties are set. * When {@link GraphObject} properties are modified, the {@link Panel.data} properties are set. */ TwoWay = 2 } /** * A Binding describes how to automatically set a property on a {@link GraphObject} * to a value of a property of data in the model. * The target property name and the data source property name are strings. * All name matching is case-sensitive. * * Register bindings by calling {@link GraphObject.bind} with a new Binding. * Existing bindings become read-only, and no new bindings may be added, * when a template (a {@link Part}) is copied. * Bindings will be shared by all copies of the template's GraphObjects. * * For example, your node data might be like: * ```js * { key: 23, say: "hello!" } * ``` * * Your simple node template might be like: * ```js * myDiagram.nodeTemplate = * new go.Node("Vertical").add( * new go.Picture("path/to/icon.jpg", { width: 32, height: 32 }), * new go.TextBlock({ font: "bold 11pt sans-serif" }) * .bind("text", "say") * ) * ``` * * The data binding causes the {@link TextBlock.text} property of * the TextBlock to be set to the value of the data's "say" property. * If the value of the "say" property of a particular data object is undefined, * the binding is not evaluated: the target property is not set. * If there is an error with the binding, you may see a message in the console log. * For this reason you may want to explicitly set the initial value for a property * when defining the GraphObject, since that value will remain as the default value * if the Binding is not evaluated. * * Bindings are not necessarily evaluated in any particular order. * Binding sources should not be (or depend in a conversion function on) the category of the data * if you might be modifying the category (e.g. by calling {@link Model.setCategoryForNodeData}), * because then some bindings might be evaluated before or after the category has been changed. * *

Conversions

* Sometimes the data value needs to be modified or converted in order * to be used as the new value of a {@link GraphObject} property. * The most common conversion functions are provided for you -- * they convert a string to a geometric class: * {@link Point.parse}, {@link Size.parse}, {@link Rect.parse}, * {@link Margin.parse}, {@link Spot.parse}, and {@link Geometry.parse}. * But you can easily define your own conversion function. * * As an example of a conversion function, let's use a function that adds some * text prefixing the data property value. * First, when called directly on a {@link GraphObject} (a TextBlock in this case): * ```js * .bind("text", "say", v => "I say: " + v) * ``` * or when passed in a call to {@link GraphObject.make}: * ```js * new go.Binding("text", "say", v => "I say: " + v) * ``` * Although simple conversions cover almost all binding cases, there are some infrequent uses * that are covered by "Advanced Conversions", discussed below. * * Conversion functions must not have any side-effects. * Conversion functions may be called frequently, so they should be fast and avoid allocating memory. * The order in which conversion functions are called is not specified and may vary. * *

OneWay and TwoWay Bindings

* By default bindings are {@link BindingMode.OneWay}. * OneWay bindings are evaluated when the {@link Panel.data} property is set * or when you call {@link Panel.updateTargetBindings} or {@link Model.set}. * OneWay bindings only transfer values from the source to the target. * * TwoWay bindings are evaluated in the source-to-target direction just as OneWay * bindings are evaluated. * However when the {@link GraphObject} target property is set, the TwoWay * bindings are evaluated in the target-to-source direction. * There is no point in having a TwoWay binding on a GraphObject property that cannot be set. * For efficiency, avoid TwoWay bindings on GraphObject properties that do not change value in your app. * Theme bindings cannot be TwoWay. * * You should not have a TwoWay binding with a source that is a node data object's key property, * i.e. on the data property whose name is the same as the value of {@link Model.nodeKeyProperty}. * Unintentionally changing the node key value to be the same as another node data's key value * may cause indeterminate behavior. * Furthermore, changing a node data key without changing any references to that node * using the key value will result in "dangling" references and inconsistent relationships. * You can make that change safely by calling {@link Model.setKeyForNodeData}, * but not via a data binding. * * The target-to-source update can also go through a conversion function. * The most common back-conversion functions are provided for you. * They convert a geometric class to a string: * {@link Point.stringify}, {@link Size.stringify}, {@link Rect.stringify}, * {@link Margin.stringify}, {@link Spot.stringify}, and {@link Geometry.stringify}. * * It is common to want to update some data properties based on changes to the diagram. * For example, as the user changes the {@link Part.location} by dragging a Node, * you can automatically keep the node's model data in sync using a TwoWay binding. * ```js * .bindTwoWay("location", "loc", go.Point.parse, go.Point.stringify) * ``` * or: * ```js * new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify) * ``` * The call to {@link Binding.makeTwoWay} changes the {@link Binding.mode} * to be {@link BindingMode.TwoWay} and specifies the {@link Binding.backConverter} * function to be the {@link Point.stringify} static function. * * Because the Binding is on the whole node (`template`), * the target object is the whole {@link Node} and the target property is "location". * The value of `data.loc` will be a string representation of the `Node.location` value. * *

Binding Sources

* The target of a Binding is always a property of a {@link GraphObject} or a {@link RowColumnDefinition}. * The source of a Binding is normally a property of a data object in the model. * But it is also possible to have the source of a Binding be the shared JavaScript object that is the value of {@link Model.modelData}. * You can specify such a binding by calling {@link Binding.ofModel}, meaning "a binding of a source that is a property of the Model.modelData". * * As an example, you might want all Nodes to use the same color. * It would be possible but not natural to bind to a property on the node data object, because that property would have to be * duplicated on all of the node data objects in the model, and updating the property would mean calling {@link Model.set} * on each node data object with the same new value. Furthermore if there happened to be no nodes at all in the model, * there would be no place to save the data. Hence using the shared {@link Model.modelData} object * would be the sensible place for that shared information. * ```js * .bindModel("stroke", "strokeColor") * ``` * or: * ```js * new go.Binding("stroke", "strokeColor").ofModel() * ``` * and to set or modify that color one would just call, within a transaction: * ```js * model.set(model.modelData, "strokeColor", "red"); * ``` * That would cause all nodes with that model data binding to be re-evaluated. * It is not commonplace to have a TwoWay Binding on "ofModel" Bindings, but that should work. * Converters also work with "ofModel" Bindings. * * And it is also possible to have the source of a Binding be another GraphObject that is in the same Part. * You can enable such a binding by calling {@link Binding.ofObject}, meaning "a binding of a source that is a property of a GraphObject". * You just have to make sure that object has a unique {@link GraphObject.name} or is the Part (or Binding Panel) itself. * The source property on the GraphObject has to be settable, and the Part must have a value for {@link Panel.data}. * (If the source property setter does not notify about property value changes, the binding mechanism will not be invoked. * Similarly, if there is no Panel.data, the binding mechanism is not active.) * * As a common kind of example of data binding between two properties of GraphObjects, * consider this Binding on a {@link Shape} which changes the color of the {@link Shape.stroke} * depending on whether the Node is selected ({@link Part.isSelected}): * ```js * .bindObject("stroke", "isSelected", s => s ? "dodgerblue" : "gray") * ``` * or: * ```js * new go.Binding("stroke", "isSelected", s => s ? "dodgerblue" : "gray").ofObject() * ``` * Note the call to {@link Binding.ofObject}, which tells the Binding that it should use as the source * a GraphObject with a particular name. However that name argument is optional -- supplying no name * (or supplying an empty string) will cause the binding to operate with the root binding Panel. * In this case that would be the Node itself. * Now with this binding whenever the value of {@link Part.isSelected} changes, this Shape's stroke changes color. * The conversion function is what changes the boolean "isSelected" value to a brush color specifier. * *

Advanced Conversions

* The binding functionality also has more advanced features for less common situations. * The source property name may be an empty string, to convert the object as a whole. * Conversion functions may take a second argument that takes the target object that is bound. * For source-to-target conversions, the second argument will be the {@link GraphObject} whose property is bound. * For target-to-source (back-)conversions, the second argument will be the source data object and * the third argument will be the {@link Model}. * * Here's an example of a two-way data-binding using two custom conversion functions working with two separate data properties. * First we define the two conversion functions. * ```js * function toLocation(data, node) { * return new go.Point(data.x, data.y); * } * * function fromLocation(loc, data, model) { * model.set(data, "x", loc.x); * model.set(data, "y", loc.y); * } * * ``` * * Then to data-bind the default template's {@link Part.location} property * to two separate data properties, "x" and "y": * ```js * .bindTwoWay("location", "", toLocation, fromLocation) * ``` * or: * ```js * new go.Binding("location", "", toLocation).makeTwoWay(fromLocation) * ``` * * The empty string argument for the *sourceprop* parameter indicates * that the whole data object should be passed to the `toLocation` function, * rather than the value of some property of that data. * The return value is used as the new value for the {@link Part.location} property. * In almost all cases the second argument is not used. * Caution: for efficiency reasons you should try to avoid using an empty source property name. * Such bindings will be evaluated much more frequently than ones whose source is a particular property name. * * The binding works normally for the source-to-target direction. * But when the target property is modified it is the source property that is * set with the back-converted property value from the target object. * Because in this example the source property name is the empty string, * and because one cannot replace the whole source data object, * any return value from the conversion function is ignored. * Instead the back-conversion function has to modify the data object directly, * as this example `fromLocation` function does. * * Note that because the source property name is the empty string, the binding system will not know * which properties are modified in the call to `fromLocation`. * Hence to support undo and redo, in order to make the data changes we have to call * {@link Model.set} so that the {@link UndoManager} can record the change, * including the previous value. * *

Replacing Items in Arrays

* However, although a TwoWay Binding cannot replace the node data object in the {@link Model.nodeDataArray}, * it is possible to replace an item in an {@link Panel.itemArray}. * So if your node data were: * * ```js * { key: 1, items: ["one", "two", "three"] } * ``` * * And if your node template included something like: * ```js * new go.Panel("Vertical", { * itemTemplate: * new go.Panel() * .add( * new go.TextBlock({ editable: true }) * .bindTwoWay("text", "") * ) * }) * .bind("itemArray", "items") * ``` * * Then the user would be able to edit any of the {@link TextBlock}s, causing the item Array to be modified, * for example resulting in this node data: * ```js * { key: 1, items: ["one", "SOME NEW TEXT HERE", "three"] } * ``` * * Note that as of version 3.0 there is a subclass of Binding: {@link ThemeBinding}. * * @category Model */ export class Binding { /** * The constructor creates a Binding. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property on the bound data object. * If this is the empty string, the whole {@link Panel.data} object is used. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param conv - A side-effect-free function converting the data property value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. * @param backconv - An optional conversion function to convert property values back to data values. * Providing this function **or specifying null** modifies this binding to set its {@link mode} to be {@link BindingMode.TwoWay}. * If you do not want a two-way binding, leave this argument unspecified or `undefined`. */ constructor(targetprop?: string, sourceprop?: string, conv?: TargetConversion, backconv?: BackConversion); /** * Create a copy of this Binding, with the same property values. * @virtual */ copy(): this; /** * @deprecated See {@link BindingMode.OneWay}. */ static readonly OneWay = BindingMode.OneWay; /** * @deprecated See {@link BindingMode.TwoWay}. */ static readonly TwoWay = BindingMode.TwoWay; /** * This static function can be used to create a function that parses * a string into an enumerated value, given the class that the enumeration values * are defined on and a default value if the string cannot be parsed successfully. * * The normal usage is to pass the result of this function as the conversion function of a {@link Binding}. * ```js * linktemplate.bind('routing', 'dataPropName', go.Binding.parseEnum(go.Link, go.Routing.Normal)); * ``` * This binding will try to parse the string that is the value of the bound data's "dataPropName" property. * If it is a legitimate enumerated value defined on the {@link Link} class, the conversion * function will return that value. * If the bound data's "dataPropName" property is not present or has an unrecognized value, * the {@link Link.routing} property gets the default value, {@link Routing.Normal}. * * Note that this method has been deprecated as enums should no longer need conversion functions * and can just be saved/loaded as numbers. It remains for compatibility with old saved models. * @param ctor - the class constructor that defines the enumerated values that are being parsed. * @param defval - the default enumerated value to return if it fails to parse the given string. * @returns a function that takes a string and returns an enumerated value. * @deprecated Instead, save/load as enum number values with no conversion. */ static parseEnum(ctor: any, defval: number): ((name: string) => number); /** * This static function can be used to convert an object to a string, * looking for commonly defined data properties, such as "text", "name", "key", or "id". * If none are found, this just calls toString() on it. * @param val */ static toString(val?: any): string; /** * Gets or sets the name of the property to be set on the target {@link GraphObject}. * The default value is the empty string; you should set this to be the name of a property. */ get targetProperty(): string; set targetProperty(value: string); /** * Gets or sets the name of the property to get from the bound data object, * the value of {@link Panel.data}. * The default value is the empty string, which results in setting the target * property to the whole data object, rather than to a property value of the data object. * If {@link sourceName} is not null, then this property names the settable * property on the {@link GraphObject} or {@link RowColumnDefinition} * that acts as the source. */ get sourceProperty(): string; set sourceProperty(value: string); /** * This read-only boolean property returns true if this is a data binding. * @since 3.0 */ get isToData(): boolean; /** * This read-only boolean property returns true if this binding is to a GraphObject source. * @see {@link ofObject} * @since 3.0 */ get isToObject(): boolean; /** * This read-only boolean property returns true if this binding is to a {@link Model.modelData} source. * @see {@link ofModel} */ get isToModel(): boolean; /** * This read-only boolean property returns true if this binding is a {@link ThemeBinding}. * @since 3.0 */ get isToTheme(): boolean; /** * Gets or sets the name of the {@link GraphObject} that should act as a source object * whose property should be gotten by this data binding. * The default value is null, which uses the bound {@link Panel.data} as the source. * If the value is a string, it should be the name of a {@link GraphObject} in the * visual tree of the {@link Panel} that is bound to the data. * Use the empty string to refer to the root panel, which is typically the whole {@link Node} or {@link Link}, * but will be a {@link Panel} if used in a {@link Panel.itemTemplate}. * The name must not contain a period. * * Binding only works if the source property is settable, not on computed or read-only properties, * and if it supports notification. * The documentation for the GraphObject (or subclass of GraphObject) property will indicate if the property is settable * and if it does not notify. * @defaultValue `null` -- the bound {@link Panel.data} is the source * @see {@link ofObject} */ get sourceName(): string | null; set sourceName(value: string | null); /** * Gets or sets a converter function to apply to the data property value * in order to produce the value to set to the target property. * This conversion function is used in both OneWay and TwoWay bindings, * when transferring a value from the source to the target. * The default value is null -- no conversion takes place. * Otherwise the value should be a function that takes one or two arguments * and returns the desired value. * However, the return value is ignored when the {@link targetProperty} * is the empty string. * * Conversion functions must not have any side-effects other than setting * the target property. In particular you should not try to modify the * structure of the visual tree in the target GraphObject's Part's visual tree. * * The function is passed the value from the source * (the first argument) and the target {@link GraphObject} (the second argument). * If the {@link targetProperty} is a property name, that property is set to * the function's return value. * If the {@link targetProperty} is the empty string, the function should * set a property on the second argument, which will be the target GraphObject. */ get converter(): TargetConversion; set converter(value: TargetConversion); /** * Gets or sets a converter function to apply to the {@link GraphObject} property value * in order to produce the value to set to a data property. * This conversion function is only used in a TwoWay binding, * when transferring a value from the target to the source. * The default value is null -- no conversion takes place. * Otherwise the value should be a function that takes one or two arguments * and returns the desired value. * However, the return value is ignored when the {@link sourceProperty} * is the empty string. * * Conversion functions must not have any side-effects other than setting * the source property. * * The function is passed the value from the target * (the first argument), the source {@link Panel.data} object (the second argument), * and the {@link Model} (the third argument). * If the {@link sourceProperty} is a property name, that property is set to * the function's return value. * If the {@link sourceProperty} is the empty string, the function should * modify the second argument, which will be the source data object. */ get backConverter(): BackConversion; set backConverter(value: BackConversion); /** * Gets or sets the directions and frequency in which the binding may be evaluated. * The default value is {@link BindingMode.OneWay}. * {@link BindingMode.TwoWay} is the other choice. * * Use OneWay bindings to initialize GraphObject properties based on model data, * or to modify GraphObject properties when the model data changes with a call to {@link Model.set}. * Use TwoWay bindings to keep model data in sync with changes to GraphObject properties. * For efficiency, avoid TwoWay bindings on GraphObject properties that do not change value in your app. * * You should not have a TwoWay binding on a node data object's key property. * * {@link ThemeBinding}s cannot be TwoWay. */ get mode(): BindingMode; set mode(value: BindingMode); /** * Modify this Binding to set its {@link mode} to be {@link BindingMode.TwoWay}, and * provide an optional conversion function to convert {@link GraphObject} property * values back to data values, as the value of {@link backConverter}. * * Use TwoWay bindings to keep model data in sync with changes to GraphObject properties. * For efficiency, avoid TwoWay bindings on GraphObject properties that do not change value in your app. * It is typical only to use TwoWay bindings on properties that are modified by tools or commands. * Examples include {@link Part.location} by {@link DraggingTool} and * {@link TextBlock.text} by {@link TextEditingTool} (only if {@link TextBlock.editable} is true). * * You should not have a TwoWay binding on a node data object's key property. * * {@link ThemeBinding}s do not support TwoWay binding. * * @param backconv * @returns this two-way Binding. */ makeTwoWay(backconv?: BackConversion): this; /** * Modify this Binding to set its {@link sourceName} property so as to identify * a {@link GraphObject} in the visual tree of the bound {@link Panel} as the data source, * instead of the {@link Panel.data} as the data source. * * This permits data binding on GraphObject properties, such as {@link Part.isSelected}. * Remember that you can reliably data bind only on settable properties, not on read-only or computed properties. * @param srcname - the {@link GraphObject.name} of an element in the visual tree of the bound {@link Panel}; * use an empty string to refer to the root panel of that visual tree, whose {@link Panel.data} is the bound data. * @returns this Binding to another GraphObject. * @see {@link sourceName} * @see {@link ofModel} */ ofObject(srcname?: string): this; /** * Modify this Binding so that the source is the {@link Model.modelData} object, * not a regular node data object or another {@link GraphObject} in the {@link Part}. * @returns this Binding to the {@link Model.modelData} object. * @see {@link isToModel} * @see {@link ofObject} */ ofModel(): this; } /** * A ThemeBinding describes how to automatically set a property on a {@link GraphObject} * to a value of a property in a {@link Theme}. * The target property name and the data source property name must be strings. * All name matching is case-sensitive. * * Register theme bindings by calling {@link GraphObject.theme} * or another method whose name starts with "theme". * * For example, your theme might be like: * ```js * { colors: { primary: 'red' } } * ``` * * Your simple node template might be like: * ```js * myDiagram.nodeTemplate = * new go.Node("Auto").add( * new go.Shape().theme("fill" , "primary"), * new go.TextBlock("Hello", { font: "bold 11pt sans-serif" }) * ); * ``` * * The theme binding causes the {@link Shape.fill} property of * the Shape to be set to the value of the theme's "primary" property. * If the value of the "primary" property of a particular theme object is undefined, * the binding is not evaluated: the target property is not set. * If there is an error with the theme binding, you may see a message in the console log. * For this reason you may want to explicitly set the initial value for a property * when defining the GraphObject, since that value will remain as the default value * if the ThemeBinding is not evaluated. * * Just like {@link Binding}s, it's possible to use different source objects. * The typical source is the Theme itself, but one can also use a property of a data object in the model. * another GraphObject in the same Part, or the shared JavaScript object that is the value of {@link Model.modelData}. * The values from these other sources are then used to perform the property lookup in the Theme object. * To use these other sources, one can call {@link GraphObject.themeData}, * {@link GraphObject.themeObject}, or {@link GraphObject.themeModel}. * Or modify the Binding by calling {@link ofData}, {@link Binding.ofObject}, or {@link Binding.ofModel}. * * Note that ThemeBindings are always OneWay. * * Existing bindings become read-only, and no new bindings may be added, * when a template (a {@link Part}) is copied. * Bindings will be shared by all copies of the template's GraphObjects. * * For more information about bindings see {@link Binding} documentation. * For more information on theming, see the Theming intro page. * @since 3.0 * @category Model */ export class ThemeBinding extends Binding { /** * The constructor creates a Theme binding, where the source value is looked up by the {@link ThemeManager}.. * @param targetprop - A string naming the target property on the target object. * This should not be the empty string. * @param sourceprop - A string naming the source property, which could be on the Theme, data object, GraphObject, or shared model data object. * If this argument is not supplied, the source property is assumed to be the same as the target property. * @param themeSource - The source object on the Theme to find the value for the source property name. * If this argument is null or not supplied, the empty string is used. * @param conv - A side-effect-free function converting the source property value to lookup in the Theme. * If the function is null or not supplied, no conversion takes place. * @param themeConverter - An optional side-effect-free function converting the theme value to the value to set the target property. * If the function is null or not supplied, no conversion takes place. */ constructor(targetprop?: string, sourceprop?: string, themeSource?: string, conv?: TargetConversion, themeConverter?: TargetConversion); /** * Gets or sets the source object on a Theme for a lookup. * * This can be used to refine where in the Theme to look, sometimes useful to avoid the need for a conversion function. * ```js * { * colors: { * sex: { * M: 'blue', * F: 'pink' * } * } * } * ... * myDiagram.nodeTemplate = * new go.Node("Auto").add( * new go.Shape().themeData("fill", "sex", "sex"), // lookup the "sex" data value in the "sex" Theme object * ... * ) * ``` * @defaultValue `''` -- the theme will be be searched without any additional object constraint */ get themeSource(): string | null; set themeSource(value: string | null); /** * Gets or sets a converter function to apply to the theme property value * in order to produce the value to set to the target property. * The default value is null -- no conversion takes place. * Otherwise the value should be a function that takes one or two arguments and returns the desired value. * * Conversion functions must not have any side-effects. * * The function is passed the value from the theme * (the first argument) and the target {@link GraphObject} (the second argument). * The {@link targetProperty} is set to the function's return value. * @since 3.0 */ get themeConverter(): TargetConversion; set themeConverter(value: TargetConversion); /** * Modify this ThemeBinding so that the source is a data object. * * Note that one can also call {@link ofObject} or {@link ofModel} as ThemeBinding is * a subclass of {@link Binding}. * * @returns this ThemeBinding with a data object source. * @see {@link ofObject} * @see {@link ofModel} */ ofData(): this; } /** * The Key type is the same as `string | number | undefined`. */ export type Key = string | number | undefined; /** * Interface for the output object of {@link Model.toIncrementalData}. * * All properties of this object are optional, as they are only included if changes occurred. * For instance, if a transaction didn't include any changes to modelData, the modelData property of this interface won't be included on the output object. * * Any shared or cyclic references within the model data will be maintained on the data included on this output object. * @category Model * @since 2.1 */ export interface IncrementalData { /** * Object containing the modified {@link Model.modelData}. */ modelData?: ObjectData; /** * Array of node keys added. Any key included will also be included in the modifiedNodeData array. */ insertedNodeKeys?: Array; /** * Array of node data objects modified. */ modifiedNodeData?: Array; /** * Array of node keys deleted. */ removedNodeKeys?: Array; /** * Array of link keys added. Any key included will also be included in the modifiedLinkData array. */ insertedLinkKeys?: Array; /** * Array of link data objects modified. */ modifiedLinkData?: Array; /** * Array of link keys deleted. */ removedLinkKeys?: Array; } /** * Models hold the essential data of a diagram, describing the basic entities and their properties and relationships * without specifying the appearance and behavior of the Nodes and Links and Groups that represent them visually. * Models tend to hold only relatively simple data, making them easy to persist by serialization as JSON or XML formatted text. * * Models hold simple data objects, not {@link Part}s such as {@link Node}s or {@link Link}s. * Node data is normally represented in a {@link Diagram} by instances of {@link Node}, * but they could be represented by simple {@link Part}s or by {@link Group}s. * A Diagram constructs Parts for its {@link Diagram.model}'s data by copying templates. * Templates are {@link Panel}s of {@link GraphObject}s that get some property values from the model data, * accessible via the {@link Panel.data} property, using data {@link Binding}. * See Using Models and Data Binding for an introduction. * * This Model class only supports holding an array of node data * and interpreting properties on that data to be able to refer to them * using unique key values. * To support simple tree-structured graphs, use a {@link TreeModel}, which inherits from this class. * To support links and grouping, use a {@link GraphLinksModel}. * * Each node data object is assumed to have a unique key value. * The {@link nodeKeyProperty} property names the property on the node data whose value * is the unique key for that node data object. * The default value for this property is "key". * You should not have a TwoWay data binding on the node key property, * because that might cause the property value to be set to a duplicate key value. * * The key values must be either strings or numbers or undefined. * If the key is undefined, or if there are duplicate key values, * the model will automatically try to assign a new unique key value. * Caution: if your keys are numbers, do not try to use string representations of those numbers as keys. * Conversely, if your keys are strings that happen to have number syntax, do not try to use those number values. * Sometimes JavaScript will automatically convert from string to number or vice-versa, but sometimes it won't. * * For example, one can define a graph consisting of just two nodes: * ```js * model.nodeDataArray = [ * { key: "Alpha" }, * { key: "Beta" } * ]; * ``` * * This model cannot detect the modification of the {@link nodeDataArray} array * or the modification of any node data object. * If you want to add or remove node data from the {@link nodeDataArray}, * call the {@link addNodeData} or {@link removeNodeData} methods. * * If you want to modify a node data object, it depends on whether the property you want to change * is a structural property that the model needs to know about, or whether it is a property * that is only used for data binding or other application-specific purposes. * * For the former case, call the appropriate method, such as * {@link setKeyForNodeData}, {@link setCategoryForNodeData}, * {@link GraphLinksModel.setToKeyForLinkData}, or {@link GraphLinksModel.setGroupKeyForNodeData}. * These methods have names that start with "set", "add", "insert", or "remove". * * For the latter case, when setting an application-specific property, typically for data binding, * and to support undo/redo, call {@link setDataProperty}. * * The {@link copyNodeData} method can be called to make a shallow copy of a node data object. * However, if some of those property values are Arrays that want not to be shared but to be copied, * you can set {@link copiesArrays} to true. This is typically very useful when dealing * with data bound item arrays. * Furthermore if the items in those copied Arrays are in fact Objects that need to be copied, * you can also set {@link copiesArrayObjects} to true, causing a copied Array to refer to * newly shallow-copied objects of the original array. * * Each model raises {@link ChangedEvent}s that you can follow by registering a listener via {@link addChangedListener}. * Read more at the Introduction page: Changed Events. * * Each model comes with its own {@link UndoManager} that is initially not enabled. * You will need to set {@link UndoManager.isEnabled} to true in order for the * UndoManager to record model changes and for your users to perform undo and redo. * * You can temporarily turn off the recording of changes by setting {@link skipsUndoManager} to true. * A number of places within the system do that routinely in order to avoid recording temporary changes, * so be sure to remember the original value beforehand and restore it afterwards. * Note that in a {@link ChangedEvent} listener you may want to ignore events that happen when {@link skipsUndoManager} is true. * * One normally saves a diagram by just saving its model. * If you can use JSON-formatted text, this is easy to do -- just call {@link toJson} * to get the string representation of the model, and save that string. * Load the diagram by replacing the {@link Diagram.model} with one created by calling * the static function {@link Model.fromJson}: * ```js * myDiagram.model = go.Model.fromJson(loadedString); * ``` * Note that JSON and other textual data formats cannot faithfully store all JavaScript functions. * {@link toJson} and {@link Model.fromJson} do not try to save and load functional property values. * You should arrange that all such functions, including event handlers, are established by your app. * {@link toJson} and {@link Model.fromJson} also cannot handle circular references; any sharing of * references will be lost too. * They also skip properties that are not enumerable, those whose names start with an underscore, and those whose values are undefined. * * Note that models also do not store the templates used by diagrams, * nor any transient or temporary parts such as {@link Adornment}s, nor any tools, * nor any {@link UndoManager} state, nor any event listeners. * These objects and all other properties of diagrams must be established by your app. * * You can add any number of properties to the {@link modelData} object, which is serialized and deserialized * into JSON just like any other model data for nodes or links. * However {@link modelData} is associated with the model as a whole and does not depend on the existence * of any node data or link data. * * It is also easy to save the changes that were recorded in the most recent transaction. * Call {@link toIncrementalJson} to generate a JSON-format string that holds the current state of modified data * plus the keys of inserted or removed data. * That method requires as an argument a {@link ChangedEvent} that represents a transaction that completed or * an undo or a redo that just finished. * * It is also possible to use such "incremental" JSON to modify an existing model. * Call {@link applyIncrementalJson}, giving it a string generated by {@link toIncrementalJson}, * to modify this model by making all of the changes recorded in the JSON text. * Note how this method is a regular instance method, whereas {@link Model.fromJson} is a static function. * @category Model */ export class Model { /** * You probably don't want to call this constructor, because this class * does not support links (relationships between nodes) or groups (nodes and links and subgraphs as nodes): * instead, create instances of a subclass such as {@link GraphLinksModel} or {@link TreeModel}. * @param nodedataarray - an optional Array containing JavaScript objects to be represented by {@link Part}s. * @param init - Optional initialization properties. */ constructor(nodedataarray?: Array, init?: Partial); /** * You probably don't want to call this constructor, because this class * does not support links (relationships between nodes) or groups (nodes and links and subgraphs as nodes): * instead, create instances of a subclass such as {@link GraphLinksModel} or {@link TreeModel}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Copies properties from this model to the given model, which must be of the same class. * This is called by {@link copy}. * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param copy */ protected cloneProtected(copy: this): void; /** * Creates a shallow copy of this Model and returns it. * The data are not copied: {@link nodeDataArray}, {@link modelData}, * {@link GraphLinksModel.linkDataArray}, {@link GraphLinksModel.archetypeNodeData} are left empty. * Nor are any Changed listeners or the UndoManager copied. * @virtual * @returns an empty copy of the model with the same properties, other than data */ copy(): Model; /** * Clear out all references to any model data. * This also clears out the {@link UndoManager}, so this operation is not undoable. * This method is called by {@link Diagram.clear}; it does not notify any {@link Diagram}s or other listeners. * This method does not unregister any Changed event listeners. * * Instead of calling this method, you may prefer to set {@link nodeDataArray} to an empty JavaScript Array. * If this model is a {@link GraphLinksModel}, you would also want to set {@link GraphLinksModel.linkDataArray} to a separate empty JavaScript Array. */ clear(): void; /** * Produce an object representing the changes in the most recent {@link Transaction}. * The structure of the object follows the same format as the JSON output from {@link toIncrementalJson}. * * Note that these incremental changes include the results of undo and redo operations. * * For {@link GraphLinksModel}s, this method requires that {@link GraphLinksModel.linkKeyProperty} is not an empty string. * If {@link GraphLinksModel.linkKeyProperty} is the empty string, that property will automatically be set to "key", * and each link data object will get a unique key value, before producing the resulting data. * * Any node or link data objects contained in the "modified..." properties will be deep copies of the data in the model. * The objects will contain proper copies of certain GoJS classes, and some common built-in objects such as Dates and RegExps. * Other classes will just be copied as plain Javascript objects, so it is best to avoid using special classes in one's data. * * This method is most commonly used when GoJS must communicate with some external data source * and maintain integrity between the two while avoiding serialization/deserialization. * * ```js * myDiagram.addModelChangedListener(e => { * if (e.isTransactionFinished) { * const dataChanges = e.model.toIncrementalData(e); * ... update React state/save to database ... * } * }); * ``` * * Caution: don't call JSON.stringify on the resulting object, because that will not properly handle any instances of * JavaScript classes that are referenced by the object's properties. * Instead call {@link toIncrementalJson}, which will produce a more compact textual serialization. * @param e - a Transaction ChangedEvent for which {@link ChangedEvent.isTransactionFinished} is true * @returns returns either null if no changes occurred, or an object containing incremental model changes for the given Transaction * @see {@link toIncrementalJson} * @since 2.1 */ toIncrementalData(e: ChangedEvent): IncrementalData; /** * Deeply copy an object or array and return the new object. * This is typically called on a {@link nodeDataArray} or {@link GraphLinksModel.linkDataArray} or data objects within them. * * By default, this method will make deep clones of arrays and JavaScript objects and maintain any shared or cyclic references. * It will properly copy any `Date` or `RegExp` object, and will call a `copy` function on any object where one exists. * It also handles certain GoJS classes: `Point`, `Size`, `Rect`, `Margin`, `Spot`, `List`, `Set`, and `Map`. * It will not handle instances of `Diagram`, `Layer`, `GraphObject`, `Tool`, `CommandHandler`, `AnimationManager` or subclasses or related classes. * * This method may be overridden. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * Only override this method when the default behavior doesn't suit the data. * @virtual * @param obj * @since 2.1 */ cloneDeep(obj: T): T; /** * Produce a JSON-format string representing the changes in the most recent {@link Transaction}. * This writes out JSON for a model, but recording only changes in the given Transaction, * with the addition of the "incremental" property to mark it as different from a complete model. * Instead of the "nodeDataArray" property (and "linkDataArray" property for {@link GraphLinksModel}s), * this will have "inserted...", "modified...", and "removed..." properties that are non-empty Arrays. * * The "modifiedNodeData" Array holds JavaScript objects. * The "insertedNodeKeys" and "removedNodeKeys" Arrays hold keys (numbers or strings) of data, * not whole objects, that have been added and/or deleted. * The "modelData" property holds the {@link Model.modelData} object, if it was modified. * * Note that it is entirely plausible for the same object be in or referenced by all three Arrays, * because a single {@link Transaction} can include adding a node, modifying it, and removing it. * * The purpose of this method is to make it easier to send incremental changes to the server/database, * instead of sending the whole model. * Whereas it has always been easy to perform "batch" updates or "file saves": * ```js * myDiagram.addModelChangedListener(e => { * if (e.isTransactionFinished) { * const json = e.model.toJson(); * // save the whole model upon each transaction completion or undo/redo * ... send to server/database ... * } * }); * ``` * You can now easily send "incremental" updates: * ```js * myDiagram.addModelChangedListener(e => { * if (e.isTransactionFinished) { * const json = e.model.toIncrementalJson(e); * // record each Transaction as a JSON-format string * ... send to server/database ... * } * }); * ``` * Note that these incremental changes include the results of undo and redo operations. * Also, when you might call {@link applyIncrementalJson}, you will need to disable your Changed listener, * so that it does not send spurious changes to your database during the process of apply incremental changes from the database. * * For {@link GraphLinksModel}s, this method requires that {@link GraphLinksModel.linkKeyProperty} is not an empty string. * If {@link GraphLinksModel.linkKeyProperty} is the empty string, that property will automatically be set to "key", * and each link data object will get a unique key value, before producing the resulting text. * The incremental JSON for GraphLinksModels will include "modifiedLinkData", "insertedLinkKeys", and "removedLinkKeys" * properties that are non-empty Arrays. * * The same restrictions on data property names and data property values applies to this method as it does to {@link toJson}. * @param e - a Transaction ChangedEvent for which {@link ChangedEvent.isTransactionFinished} is true * @param classname - for the written model, defaults to the name of the class of the model */ toIncrementalJson(e: ChangedEvent, classname?: string): string; /** * Generate a string representation of the persistent data in this model, in JSON format, * that can be read in later with a call to {@link Model.fromJson}. * * Object properties that are not enumerable or whose names start with "_" are not written out. * * Functions are not able to be written in JSON format, so any properties that have function values * will not be saved in the JSON string. * * There must not be any circular references within the model data. * Any sharing of object references will be lost in the written JSON. * * Most object classes cannot be serialized into JSON without special knowledge and processing at both ends. * The {@link toJson} and {@link Model.fromJson} methods automatically do such processing for numbers that are NaN * and for objects that are of class {@link Point}, {@link Size}, {@link Rect}, {@link Margin}, {@link Spot}, * {@link Brush} (but not for brush patterns), and for {@link Geometry}. * For instances of those classes, special objects are written out with a property named "class" whose value * will be one of the special cases that will be substituted by {@link Model.fromJson}: * "NaN", "Date", "go.Point", "go.Size", "go.Rect", "go.Margin", "go.Spot", "go.Brush", "go.Geometry". * * However, we recommend that you use Binding converters (static functions named "parse" and "stringify") * to represent Points, Sizes, Rects, Margins, Spots, and Geometries as string values in your data, rather than as Objects. * This makes the JSON text smaller and simpler and easier to read. * * As a special case when serializing an object, if the property is named "points" and the * property value is a {@link List} of {@link Point}s, it will write an Array of numbers. * * Note that this is a method on the {@link Model} class. * It cannot render unmodeled Parts such as the background grid or any Parts that you have added directly to a Diagram. * * Typical usage: * ```js * const modelAsText = myDiagram.model.toJson(); * // now save this text string by sending it to your database * ``` * @param classname - The optional name of the model class to use in the output; * for the standard models, this is their class name prefixed with "go.". * @returns a String in JSON format containing all of the persistent properties of the model. */ toJson(classname?: string): string; /** * Modify this model by applying the changes given in an "incremental" model change in JSON format * generated by {@link toIncrementalJson}. * The expected properties of the argument are described at {@link toIncrementalJson}. * Incremental changes must be applied in the same order that the changes occurred in the original model. * * This requires the "incremental" property to be present and to be a number, as specified by {@link toIncrementalJson}. * All of the top-level properties in the JSON, such as {@link nodeKeyProperty}, must be the same as for this model. * Note that if the model is a {@link GraphLinksModel}, you will have to have set {@link GraphLinksModel.linkKeyProperty} * to the name of a property, the same both in the {@link Diagram.model} as well as in the data that you pass to this method. * * This conducts a transaction. * @param s - a String in JSON format containing modifications to be performed to the model, * or a JavaScript Object parsed from such a string */ applyIncrementalJson(s: string | ObjectData): void; /** * This static function parses a string in JSON format that was written by {@link Model.toJson}, * and then constructs, initializes, and returns a model with that information. * * Note that properties with values that are functions are not written out by {@link toJson}, * so reading in such a model will require constructing such a model, initializing its functional property values, * and explicitly passing it in as the second argument. * * In order to serialize instances of some classes and enumerated values and some other cases, * {@link Model.toJson} writes out special Objects that this {@link Model.fromJson} function substitutes * with the intended values. * Those special objects will have a property named "class" whose value will be one of the special substitution cases: * "NaN", "Date", "go.EnumValue" (for compatibility), "go.Point", "go.Size", "go.Rect", "go.Margin", "go.Spot", "go.Brush", "go.Geometry". * * As a special case when deserializing an object, if the property is named "points" and the * property value is an Array with an even number of numbers, it will substitute a {@link List} of {@link Point}s. * * Typical usage: * ```js * const modelAsText = ...; // fetch the model in textual format from a database * myDiagram.model = go.Model.fromJson(modelAsText); * ``` * @param s - a String in JSON format containing all of the persistent properties of the model, or an Object already read from JSON text. * @param model - an optional model to be modified; if not supplied, it constructs and returns a new model whose name is specified by the "class" property. * @returns the supplied or created model loaded with data from the given string. */ static fromJson(s: string | ObjectData, model?: Model): Model; /** * Gets or sets the number of digits after the decimal point for 'points' values written out * in an Array for the {@link Link#points} property. * * A new value must be a non-negative integer less than or equal to 100; * typically the value will be zero, 1, 2, or 3. * * The default value is 100. Values larger than 16 will cause each number to be written out with * however many decimal digits are needed without trailing zeros. * @see {@link Point.stringifyFixed} * @since 3.0 */ get pointsDigits(): number; set pointsDigits(value: number); /** * Gets or sets the name of this model. * The initial name is an empty string. * The value must not be null. */ get name(): string; set name(value: string); /** * Gets or sets the name of the format of the diagram data. * The default value is the empty string. * The value must not be null. * Use different values to prevent parts from one model to be copy/pasted or drag-and-dropped into another diagram/model. */ get dataFormat(): string; set dataFormat(value: string); /** * Gets or sets whether this model may be modified, such as adding nodes. * By default this value is false. * Setting the {@link nodeDataArray} to something that is not a true Array of Objects * will cause this to be set to true. * * Model methods and property setters do not heed this property. * It is up to code that uses a model to check this property when it might want to * prevent changes to the model. */ get isReadOnly(): boolean; set isReadOnly(value: boolean); /** * Gets or sets a JavaScript Object that can hold programmer-defined property values for the model as a whole, * rather than just for one node or one link. * * By default this an object with no properties. * Any properties that you add to this object will be written out by {@link toJson} * and will be restored by {@link Model.fromJson}, if the following conditions are true: * - the property is enumerable and its name does not start with an underscore ('_') * - the property value is not undefined and is not a function * - the model knows how to convert the property value to JSON format * - property values that are Objects or Arrays form a tree structure -- no shared or cyclical references * * The new value must not be null. * * This data object must not be used in the {@link nodeDataArray} or {@link GraphLinksModel.linkDataArray} * or in any {@link Panel.itemArray}. * * Most object classes cannot be serialized into JSON without special knowledge and processing at both ends. * The {@link toJson} and {@link Model.fromJson} methods automatically do such processing for numbers that are NaN * and for objects that are of class {@link Point}, {@link Size}, {@link Rect}, {@link Margin}, {@link Spot}, * {@link Brush} (but not for brush patterns), and for {@link Geometry}. * * At the current time one cannot have a {@link Diagram} as a binding target. * Calling {@link setDataProperty} will work to change a property value, but there are no target bindings in any Diagrams to be updated. * Because the binding mechanism is unavailable for this object, we recommend that when you want to save a model * that you explicitly set properties on this object just before calling {@link toJson}. * When loading a model, call {@link Model.fromJson} and explicitly get the properties that you want to set on a Diagram. */ get modelData(): ObjectData; set modelData(value: ObjectData); /** * Register an event handler that is called when there is a ChangedEvent. * * This registration does not raise a {@link ChangedEvent}. * In case a Diagram's Model may be replaced, you may prefer calling {@link Diagram.addModelChangedListener} instead of this method. * * Event listeners are not written out by {@link toJson}. * * Do not add or remove Changed listeners during the execution of a Changed listener. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link removeChangedListener} * @see {@link Diagram.addModelChangedListener} * @returns this Model */ addChangedListener(listener: ChangedEventHandler): this; /** * Unregister an event handler listener. * * This deregistration does not raise a {@link ChangedEvent}. * In case a Diagram's Model may be replaced, you may prefer calling {@link Diagram.removeModelChangedListener} instead of this method. * @param listener - a function that takes a {@link ChangedEvent} as its argument. * @see {@link addChangedListener} * @see {@link Diagram.removeModelChangedListener} */ removeChangedListener(listener: ChangedEventHandler): void; /** * Call this method to notify that the model or its objects have changed. * This constructs a {@link ChangedEvent} and calls all Changed listeners. * @param change - specifies the general nature of the change; typically the value is {@link ChangeType.Property}. * @param propertyname - names the property that was modified, or a function that takes an Object and returns the property value. * @param obj - the object that was modified, typically a {@link GraphObject}, {@link Diagram}, or a {@link Model}. * @param oldval - the previous or older value. * @param newval - the next or newer value. * @param oldparam - an optional value that helps describe the older value. * @param newparam - an optional value that helps describe the newer value. */ raiseChangedEvent(change: ChangeType, propertyname: string | ((obj: ObjectData, val: any) => any), obj: ObjectData, oldval: any, newval: any, oldparam?: any, newparam?: any): void; /** * Call this method to notify about a data property having changed value. * This constructs a {@link ChangedEvent} and calls all Changed listeners. * * You should call this method only if the property value actually changed. * This method is called by {@link setDataProperty}. * @param data - the data object whose property changed value. * @param propertyname - the name of the property, or a function that takes an Object and returns the property value. * @param oldval - the previous or old value for the property. * @param newval - the next or new value for the property. * @param oldparam - an optional value additionally describing the old value. * @param newparam - an optional value additionally describing the new value. */ raiseDataChanged(data: ObjectData, propertyname: string | ((obj: ObjectData, val: any) => any), oldval: any, newval: any, oldparam?: any, newparam?: any): void; /** * Gets or sets the {@link UndoManager} for this Model. * * The default UndoManager has its {@link UndoManager.isEnabled} property set to false. * If you want users to undo and redo, you should set that property to true once you have initialized the Diagram or its Model. * * This property setter does not raise a {@link ChangedEvent}. */ get undoManager(): UndoManager; set undoManager(value: UndoManager); /** * Gets or sets whether {@link ChangedEvent}s are not recorded by the {@link UndoManager}. * The initial and normal value is false. * WARNING: while this property is true do not perform any changes that cause any previous transactions * to become impossible to undo. * * When this property is true, changing the Model or any data object does not call {@link UndoManager.handleChanged}. * Even when this property is true, * transactions (such as calls to {@link startTransaction}) and undo/redo (such as calls to {@link CommandHandler.undo}) * are still delegated to the {@link undoManager}. * * You should set this to true only temporarily, and you should remember its previous value before setting this to true. * When finishing the period for which you want the UndoManager to be disabled, * do not blindly set this property to false. * You should set this back to the value it had before you set it to true. * For more permanent disabling of the {@link UndoManager}, set {@link UndoManager.isEnabled} to false. * * This property is also set when setting {@link Diagram.skipsUndoManager}. * Setting this property does not raise a {@link ChangedEvent}. */ get skipsUndoManager(): boolean; set skipsUndoManager(value: boolean); /** * (undocumented) * This is called during an undo or redo to modify the model or its objects. * * This does not raise a {@link ChangedEvent}. * @virtual * @param e - This describes the change that needs to be done. * @param undo - If true, this method should restore the older state, otherwise the newer state. */ changeState(e: ChangedEvent, undo: boolean): void; /** * Begin a transaction, where the changes are held by a {@link Transaction} object * in the {@link UndoManager}. * This just calls {@link UndoManager.startTransaction}. * @param tname - a descriptive name for the transaction. * @returns the value returned by {@link UndoManager.startTransaction}. * @see {@link commit} */ startTransaction(tname?: string): boolean; /** * Commit the changes of the current transaction. * This just calls {@link UndoManager.commitTransaction}. * @param tname - a descriptive name for the transaction. * @returns the value returned by {@link UndoManager.commitTransaction}. */ commitTransaction(tname?: string): boolean; /** * Rollback the current transaction, undoing any recorded changes. * This just calls {@link UndoManager.rollbackTransaction}. * @returns the value returned by {@link UndoManager.rollbackTransaction}. */ rollbackTransaction(): boolean; /** * Starts a new transaction, calls the provided function, and commits the transaction. * Code is called within a try-finally loop. * If the function does not return normally, this rolls back the transaction rather than committing it. * Example usage: * ```js * model.commit(m => m.addNodeData({ counter: myCounter++ }), "Added Node"); * ``` * @param func - the function to call as the transaction body * @param tname - a descriptive name for the transaction, or null to temporarily set {@link skipsUndoManager} to true; * if no string transaction name is given, an empty string is used as the transaction name */ commit(func: (m: Model) => void, tname?: string | null): void; /** * Find a {@link Part} corresponding to the given data and * call its {@link Panel.updateTargetBindings} method, in each {@link Diagram} * that uses this Model. * * Caution: setting a data property without calling {@link setDataProperty} * and then calling this updateTargetBindings method will update GraphObjects that are bound to the property, * but such data settings will not be recorded in the UndoManager and therefore will not be undone/redone, * causing an inconsistency between the GraphObjects and the part data. * @param data - The data object in this model that was modified. * @param srcpropname - If not present or the empty string, * update all bindings on the target {@link Part} or item {@link Panel} * otherwise update only those bindings using this source property name. */ updateTargetBindings(data: ObjectData, srcpropname?: string): void; /** * Gets or sets the name of the data property that returns a unique id number or string for each node data object. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return the unique key value; * if the second argument is supplied, the function should modify the node data object so that it has that new value as its unique key value. * The default value is the name 'key', meaning that it expects the data to have a property named 'key' if it has a key value. * The name must not be null or the empty string. * You must set this property before assigning the {@link nodeDataArray}. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getKeyForNodeData} */ get nodeKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set nodeKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * Given a node data object return its unique key: a number or a string. * This returns undefined if there is no key value. * * It is possible to change the key for a node data object by calling {@link setKeyForNodeData}. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link nodeKeyProperty} * @see {@link setKeyForNodeData} * @see {@link findNodeDataForKey} */ getKeyForNodeData(nodedata: ObjectData): Key; /** * Change the unique key of a given node data that is already in this model. * The new key value must be unique -- i.e. not in use by another node data object. * You can call {@link findNodeDataForKey} to check if a proposed new key is already in use. * * This operation will check all data objects in the model and replace all references * using the old key value with the new one. * * If this is called on a node data object that is not (yet) in this model, * this unconditionally modifies the property to the new key value. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @param key * @see {@link nodeKeyProperty} * @see {@link getKeyForNodeData} */ setKeyForNodeData(nodedata: ObjectData, key: Key): void; /** * Gets or sets a function that returns a unique id number or string for a node data object. * This function is called by {@link makeNodeDataKeyUnique} * when a node data object is added to the model, either as part of a new * {@link nodeDataArray} or by a call to {@link addNodeData}, to make sure the value of * {@link getKeyForNodeData} is unique within the model. * * The value may be null in order to cause {@link makeNodeDataKeyUnique} behave in the standard manner. * (The default value is null.) * You may want to supply a function here in order to make sure all of the automatically generated keys * are in a particular format. * Setting this property after setting {@link nodeDataArray} has no real effect until there is a call * to {@link addNodeData}. * * If you want to ensure that this function is called when copying data that already has a key, * set {@link copiesKey} to false, which is its default value. * This is typically useful when copying a node from a Palette, where the key it has in the Palette's Model * happens to be unique within the target Diagram's Model. * If you set {@link copiesKey} to true on the target Diagram's model, * the original key value will be copied and retained if it is already unique within the target model. * * If a node data object is already in the model and you want to change its key value, * call {@link setKeyForNodeData} with a new and unique key. */ get makeUniqueKeyFunction(): ((model: Model, data: ObjectData) => Key) | null; set makeUniqueKeyFunction(value: ((model: Model, data: ObjectData) => Key) | null); /** * Decide if a given node data object is in this model, using reference equality. * * If you do not have a reference to the particular data object that is in the {@link nodeDataArray}, * you may need to search for it by iterating through that Array, * or by finding the desired {@link Node} or simple {@link Part} in a {@link Diagram} and getting that node's {@link Panel.data}, * or most likely by calling {@link findNodeDataForKey}. * @param nodedata - a JavaScript object represented by a node, group, or non-link; if null, this predicate will return false * @returns true if it is a node data object in this model; false otherwise. */ containsNodeData(nodedata: ObjectData | null): boolean; /** * Given a number or string, find the node data object in this model * that uses the given value as its unique key. * @param key - a string or a number. * @returns null if the key is not present in the model, * or if the key is null or undefined or not a string or number. * @see {@link containsNodeData} * @see {@link getKeyForNodeData} */ findNodeDataForKey(key: Key): ObjectData | null; /** * Gets or sets the array of node data objects that correspond to {@link Node}s, * {@link Group}s, or non-Link {@link Part}s in the {@link Diagram}. * The initial value is an empty Array. * * For each Object in the Array, {@link getKeyForNodeData} should return a number or string * uniquely identifying the node data within the model. * If it returns undefined, this calls {@link makeNodeDataKeyUnique}, * to make sure the node data has a unique key. * These key values may be used by other objects to refer to that particular node data object. * If more than one node data object has the same key, * there may be some confusion about which object to reference. * * If you want to use a custom data property for holding the unique key value on a node data object, * you should set {@link nodeKeyProperty} before you set this `nodeDataArray` property. * * Adding or removing data from this Array will not notify this model or the diagram * that there are any new nodes or that any nodes have been deleted. * Instead you should call {@link addNodeData} or {@link removeNodeData}. */ get nodeDataArray(): Array; set nodeDataArray(value: Array); /** * This method is called when a node data object is added to the model to make sure that * {@link getKeyForNodeData} returns a unique key value. * * The key value should be unique within the set of data managed by this model: * {@link nodeDataArray}. * If the key is already in use, this will assign an unused number to the * {@link nodeKeyProperty} property on the data. * * If you want to customize the way in which node data gets a unique key, * you can set the {@link makeUniqueKeyFunction} functional property. * * If the node data object is already in the model and you want to change its key value, * call {@link setKeyForNodeData} and give it a new unique key value. * @param nodedata - a JavaScript object represented by a node, group, or non-link. */ makeNodeDataKeyUnique(nodedata: ObjectData): void; /** * When you want to add a node or group to the diagram, * call this method with a new data object. * This will add that data to the {@link nodeDataArray} and * notify all listeners that a new node data object has been inserted into the collection. * * To remove a node from the diagram, you can remove its data object by calling {@link removeNodeData}. * * To add or remove an object or value from an item array, call {@link insertArrayItem} or {@link removeArrayItem}. * @param nodedata - a JavaScript object represented by a node, group, or non-link. */ addNodeData(nodedata: ObjectData): void; /** * Add to this model all of the node data held in an Array or in an {@link Iterable} of node data objects. * @param coll - a collection of node data objects to add to the {@link nodeDataArray} */ addNodeDataCollection(coll: Iterable | Array): void; /** * When you want to remove a node or group from the diagram, * call this method with an existing data object. * This will remove that data from the {@link nodeDataArray} and * notify all listeners that a node data object has been removed from the collection. * * If you do not have a reference to the particular data object that is in the {@link nodeDataArray}, * you may need to search for it by iterating through that Array, * or by finding the desired {@link Node} or simple {@link Part} in a {@link Diagram} and getting that node's {@link Panel.data}, * or most likely by calling {@link findNodeDataForKey}. * * Removing a node data from a model does not automatically remove * any connected link data from the model. * Removing a node data that represents a group does not automatically remove * any member node data or link data from the model. * * To add a node to the diagram, you can add its data object by calling {@link addNodeData}. * * To add or remove an object or value from an item array, call {@link insertArrayItem} or {@link removeArrayItem}. * @param nodedata - a JavaScript object represented by a node, group, or non-link. */ removeNodeData(nodedata: ObjectData): void; /** * Remove from this model all of the node data held in an Array or in an {@link Iterable} of node data objects. * @param coll - a collection of node data objects to remove from the {@link nodeDataArray} */ removeNodeDataCollection(coll: Iterable | Array): void; /** * Take an Array of node data objects and update {@link nodeDataArray} without replacing * the Array and without replacing any existing node data objects that are identified by key. * * For node data objects that have the same key value, this makes calls to {@link setDataProperty} * to update the existing node data object. * For new keys, this calls {@link cloneDeep} to copy the data and then {@link addNodeData} to add a new node to the model. * For existing nodes that have keys that are not present in the given Array, * this calls {@link removeNodeData} to remove the existing node from the model. * * This method is typically used when GoJS is being used within an application that is maintaining state * related to the diagram model. When state is updated, this method can be called to keep the GoJS model synchronized. * Any updates to the data should use new references since this method will use reference equality to check * if a node data object needs to be updated. * * This method does not conduct a transaction. * @param arr * @since 2.1 */ mergeNodeDataArray(arr: Array): void; /** * Gets or sets a function that makes a copy of a node data object. * * You may need to set this property in order to ensure that a copied {@link Node} is bound * to data that does not share certain data structures between the original node data and the copied node data. * This property value may be null in order to cause {@link copyNodeData} to make a shallow copy of a JavaScript Object. * The default value is null. * * The first argument to the function will be a node data object (potentially a {@link Part}'s {@link Panel.data}). * The second argument to the function will be this Model itself. * * It is common to implement a copying function when the node data has an Array of data * and that Array needs to be copied rather than shared. * Often the objects that are in the Array also need to be copied. */ get copyNodeDataFunction(): ((data: ObjectData, model: Model) => ObjectData) | null; set copyNodeDataFunction(value: ((data: ObjectData, model: Model) => ObjectData) | null); /** * Gets or sets whether the default behavior for {@link copyNodeData} or {@link GraphLinksModel.copyLinkData} * makes copies of property values that are Arrays. * This only copies Arrays that are top-level property values in data objects, not for Arrays that are in nested objects. * Copying Arrays will also copy any array items that are Objects when {@link copiesArrayObjects} is true. * * The default value is false. * It is commonplace to set {@link copiesArrayObjects} to true when setting this property to true. * This property does not affect any behavior when the value of {@link copyNodeDataFunction} * or {@link GraphLinksModel.copyLinkDataFunction} has been set to a function. * * Caution: if you want a copied data object to share some Arrays but not others, * you will need to provide your own copying function as {@link copyNodeDataFunction} rather than setting * this property to true. * * Warning: there should not be any cyclical references within the model data. * @see {@link copiesArrayObjects} * @see {@link copyNodeDataFunction} */ get copiesArrays(): boolean; set copiesArrays(value: boolean); /** * Gets or sets whether the default behavior for {@link copyNodeData} or {@link GraphLinksModel.copyLinkData} * when copying Arrays also copies array items that are Objects. * This only covers copying Objects that are items in Arrays that are copied when {@link copiesArrays} is true. * Copying an Object when this property is true also recursively copies any Arrays that are property values. * It also assumes that the object's constructor can be called with no arguments. * * The default value is false. * This property does not affect any behavior when the value of {@link copyNodeDataFunction} * or {@link GraphLinksModel.copyLinkDataFunction} has been set to a function. * This property has no effect unless {@link copiesArrays} is true. * * Caution: if you want a copied data object to share some references but not others, * you will need to provide your own copying function as {@link copyNodeDataFunction} rather than setting * this property and {@link copiesArrays} to true. * * Warning: there should not be any cyclical references within the model data. * @see {@link copiesArrays} * @see {@link copyNodeDataFunction} */ get copiesArrayObjects(): boolean; set copiesArrayObjects(value: boolean); /** * Gets or sets whether the default behavior for {@link copyNodeData} or {@link GraphLinksModel.copyLinkData} * when copying properties of a data object also copies the key property value. * Set this to false in order to force a unique key generation for data copied from another Diagram, such as a Palette. * Set this to true in order to keep the same key as the source data object, unless it is not unique in the target model. * You may need to set it to true on both the source model as well as the destination model. * * The default value is false. * This property does not affect any behavior when the value of {@link copyNodeDataFunction} has been set to a function. * * @see {@link copiesArrays} * @see {@link copyNodeDataFunction} * @since 2.0 */ get copiesKey(): boolean; set copiesKey(value: boolean); /** * Make a copy of a node data object. * This uses the value of {@link copyNodeDataFunction} to actually perform the copy, unless that property is null. * When it is null the default behavior is to just make a shallow copy of the JavaScript Object. * * However when {@link copiesArrays} is true, this will make a copy of property values that are JavaScript Arrays. * This is useful when you do not want the Arrays to be shared between the node data objects. * Note that if you want to copy some property values that are Arrays but not other properties that are Arrays, * you cannot use {@link copiesArrays} but must implement your own {@link copyNodeDataFunction}. * * In addition when {@link copiesArrayObjects} is true, if items in the Array being copied are JavaScript Objects, * those objects are copied, recursively. * This is useful when the items in copied Arrays are themselves objects that need to be copied. * Note that if you want to share references to some but not all of the objects in copied Arrays you cannot use * {@link copiesArrayObjects} but must implement your own {@link copyNodeDataFunction}. * * This does not modify the model -- the returned data object is not added to this model. * This assumes that the data's constructor can be called with no arguments. * * Models should not have any references to Diagrams or GraphObjects or Tools or Layouts or other objects * that form a {@link Diagram}. * * Warning: there should not be any cyclical references within the model data, unless you * either do not turn on {@link copiesArrays} or {@link copiesArrayObjects} or unless you have * supplied your own {@link copyNodeDataFunction} that can handle cyclical references. * @virtual * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link addNodeData} */ copyNodeData(nodedata: ObjectData): ObjectData | null; /** * (undocumented) * This function (if not null) is called towards the end of {@link Diagram.copyParts} * in order to support custom data copying operations that depend on references between the parts. * * The first argument to the function is a {@link Map | go.Map} mapping original data objects to copied data objects. * The second argument to the function is this Model, the destination model for the copied parts. * The third argument to the function is the source Model, of the original data objects. */ get afterCopyFunction(): ((map: Map, destModel: Model, srcModel: Model) => void) | null; set afterCopyFunction(value: ((map: Map, destModel: Model, srcModel: Model) => void) | null); /** * Change the value of some property of a node data, a link data, an item data, or the {@link Model.modelData}, * given a string naming the property and the new value, * in a manner that can be undone/redone and that automatically updates any bindings. * * This gets the old value of the property; if the value is the same as the new value, no side-effects occur. * This calls {@link raiseDataChanged} to notify about the change. * * Note that it is insufficient to modify an item Array (for example by pushing a new item onto the Array) and * then calling `setDataProperty(data, "items", data.items)` because the value of * `data.items` is still the same reference. * Instead you will want to call {@link insertArrayItem}, {@link addArrayItem}, or {@link removeArrayItem}. * * If you modify the property that is the {@link nodeKeyProperty}, this will call {@link setKeyForNodeData}. * * If you modify the property that is the {@link nodeCategoryProperty} or the {@link GraphLinksModel.linkCategoryProperty}, * this will call {@link setCategoryForNodeData} or {@link GraphLinksModel.setCategoryForLinkData}. * But if the category might change, {@link Binding} sources should not be (or depend in a conversion function on) the category of the data, * because then some bindings might be evaluated before or after the category has been changed. * @virtual * @param data - a JavaScript object typically the value of a {@link Panel.data} and represented by a Node, Link, Group, simple Part, * or item in a {@link Panel.itemArray}; or this model's {@link modelData}. * @param propname - a string that is not null or the empty string. * @param val - the new value for the property. * @see {@link set} */ setDataProperty(data: ObjectData, propname: string, val: any): void; /** * A synonym for {@link setDataProperty} * @param data - a JavaScript object typically the value of a {@link Panel.data} and represented by a Node, Link, Group, simple Part, * or item in a {@link Panel.itemArray}; or this model's {@link modelData}. * @param propname - a string that is not null or the empty string. * @param val - the new value for the property. * @see {@link setDataProperty} */ set(data: ObjectData, propname: string, val: any): void; /** * This is similar to Object.assign, * but safely calls {@link setDataProperty} for each property other than a key property. * This does not delete any properties on the DATA object, * although properties may be set to undefined if they are set that way on the PROPS object. * @param data - a data object * @param props - an Object holding various properties whose values are to be assigned to the DATA object */ assignAllDataProperties(data: ObjectData, props: ObjectData): void; /** * Add an item at the end of a data array that may be data bound by a {@link Panel} as its {@link Panel.itemArray}, * in a manner that can be undone/redone and that automatically updates any bindings. * * This also calls {@link raiseChangedEvent} to notify all listeners about the {@link ChangeType.Insert}. * * If you want to add a new node or part to the diagram, call {@link addNodeData}. * @param arr - an Array that is the value of some {@link Panel}'s {@link Panel.itemArray}. * @param val - the new value to be pushed onto the array. * @see {@link insertArrayItem} */ addArrayItem(arr: Array, val: any): void; /** * Add an item to a data array that may be data bound by a {@link Panel} as its {@link Panel.itemArray}, * given a new data value and the index at which to insert the new value, in a manner that can be undone/redone and that automatically updates any bindings. * * This also calls {@link raiseChangedEvent} to notify all listeners about the {@link ChangeType.Insert}. * * If you want to add a new node or part to the diagram, call {@link addNodeData}. * @param arr - an Array that is the value of some {@link Panel}'s {@link Panel.itemArray}. * @param idx - the zero-based array index where the new value will be inserted; use -1 to push the new value on the end of the array. * @param val - the new value to be inserted into the array. * @see {@link removeArrayItem} */ insertArrayItem(arr: Array, idx: number, val: any): void; /** * Remove an item from a data array that may be data bound by a {@link Panel} as its {@link Panel.itemArray}, * given the index at which to remove a data value, in a manner that can be undone/redone and that automatically updates any bindings. * * This also calls {@link raiseChangedEvent} to notify all listeners about the {@link ChangeType.Remove}. * * If you want to remove a node from the diagram, call {@link removeNodeData}. * * Note that there is no version of this method that takes an item value instead of an index into the array. * Because item arrays may hold any JavaScript value, including numbers and strings, there may be duplicate entries with that value in the array. * To avoid ambiguity, removing an item from an array requires an index. * @param arr - an Array that is the value of some {@link Panel}'s {@link Panel.itemArray}. * @param idx - the zero-based array index of the data item to be removed from the array; * if not supplied it will remove the last item of the array. * @see {@link insertArrayItem} */ removeArrayItem(arr: Array, idx?: number): void; /** * Gets or sets the name of the node data property that returns a string naming that data's category. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return the category name; * if the second argument is supplied, the function should modify the node data object so that it has that new category name. * The default value is the string 'category', meaning that it expects the data to have a property named 'category' if it cares to name a category. * This is used by the diagram to distinguish between different kinds of nodes. * The name must not be null. * If the value is an empty string, * {@link getCategoryForNodeData} will return an empty string for all node data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getCategoryForNodeData} * @see {@link setCategoryForNodeData} */ get nodeCategoryProperty(): string | ((a: ObjectData, b?: string) => string); set nodeCategoryProperty(value: string | ((a: ObjectData, b?: string) => string)); /** * Find the category of a given node data, a string naming the node template * or group template or part template * that the {@link Diagram} should use to represent the node data. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link nodeCategoryProperty} * @see {@link setCategoryForNodeData} */ getCategoryForNodeData(nodedata: ObjectData): string; /** * Change the category of a given node data, a string naming the node template * or group template or part template * that the {@link Diagram} should use to represent the node data. * * Changing the node template for a node data will cause the existing {@link Node}, {@link Group}, or {@link Part} * to be replaced with a new instance of the same class * created by copying the new node template and applying any data-bindings. * That means that the templates in the {@link Diagram.nodeTemplateMap} or {@link Diagram.groupTemplateMap} * must be instances of the same class -- one cannot convert a {@link Node} into a {@link Group} or vice-versa * by setting the category. * * Binding sources should not be (or depend in a conversion function on) the category of the data * if you might be modifying the category, because then some bindings might be evaluated * before or after the category has been changed. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @param cat - Must not be null. * @see {@link nodeCategoryProperty} * @see {@link getCategoryForNodeData} */ setCategoryForNodeData(nodedata: ObjectData, cat: string): void; } /** * GraphLinksModels support links between nodes and grouping nodes and links into subgraphs. * GraphLinksModels hold node data and link data in separate arrays. * Node data is normally represented in a {@link Diagram} by instances of {@link Node}, * but they could be represented by simple {@link Part}s or by {@link Group}s. * Link data should be represented by instances of {@link Link}. * * Each link data object is assumed to have two values, one referring to the node that the * link is coming from and one that the link is going to. * The {@link linkFromKeyProperty} property names the property on the link data whose value * is the key of the "from" node. * The {@link linkToKeyProperty} property names the property on the link data whose value * is the key of the "to" node. * The default values for these properties are "from" and "to" respectively. * * For example, one can define a graph consisting of two nodes with one link connecting them: * ```js * model.nodeDataArray = [ * { key: "Alpha" }, * { key: "Beta" } * ]; * model.linkDataArray = [ * { from: "Alpha", to: "Beta" } * ]; * ``` * * If you want to have subgraphs in your diagram, where a group node contains some number of nodes and links, * you need to declare that some node data actually represent groups, * and you need to provide a reference from a member node data to its containing group node data. * The {@link nodeIsGroupProperty} property names the property on a node data that is true * if that node data represents a group. * The {@link nodeGroupKeyProperty} property names the property on a node data whose value * is the key of the containing group's node data. * The default values for these properties are "isGroup" and "group" respectively. * * For example, one can define a graph consisting of one group containing a subgraph of * two nodes connected by a link, with a second link from that group to a third node * that is not a member of that group: * ```js * model.nodeDataArray = [ * { key: "Group1", isGroup: true}, * { key: "Alpha", group: "Group1" }, * { key: "Beta", group: "Group1" }, * { key: "Gamma" } * ]; * model.linkDataArray = [ * { from: "Alpha", to: "Beta" }, * { from: "Group1", to: "Gamma" } * ]; * ``` * * GraphLinksModels also support distinguishing the "port" element of a node to which * a link can connect, at either end of the link. * This identification is a string that names the "port" element in the node. * However, you need to set the {@link linkFromPortIdProperty} and/or * {@link linkToPortIdProperty} properties before the model is able to * get the "port id" information from the link data. * * For example, one can define a graph consisting of a "subtraction" node and two inputs and one output. * The "subtraction" node has two distinct inputs called "subtrahend" and "minuend"; * the output is called "difference". * ```js * model.linkFromPortIdProperty = "fromPort"; // necessary to remember portIds * model.linkToPortIdProperty = "toPort"; * model.nodeDataArray = [ * { key: 1, constant: 5 }, // a constant input node * { key: 2, constant: 2 }, // another constant node * { key: 3, operation: "subtract" }, * { key: 4, value: 3 } // the output node * ]; * model.linkDataArray = [ * { from: 1, to: 3, toPort: "subtrahend" }, * { from: 2, to: 3, toPort: "minuend" }, * { from: 3, to: 4, fromPort: "difference" } * ]; * ``` * In this case links connected to node 3 (which is the subtraction operation) * are distinguished by port id. * The connections to the other nodes do not have any port identification, * presumably because there is only one port on those nodes, representing the node value. * * Note that there is no requirement that the link data objects have any kind of unique identifier, unlike for node data. * There is no expectation that there be references to link data in the model, so there is no need for such an identifier. * When there are multiple links connecting two ports, the only way to distinguish the links in the model * is by reference to the particular link data object. * This is why there are two methods on the Diagram class for Nodes, {@link Diagram.findNodeForKey} and {@link Diagram.findNodeForData}, * but there is only the one method for Links, {@link Diagram.findLinkForData}. * * However you may wish to have the model maintain string or number identifiers on the link data just as all models do for node data. * To get that behavior, so that you can call {@link findLinkDataForKey}, you need to set {@link linkKeyProperty} to be a non-empty string. * Just as with the assignment of node keys, you can customize the assignment of link keys by setting * {@link makeUniqueLinkKeyFunction} to a function that returns a unique identifier. * * This model does not support the modification of whether a node data object is a group. * * This model cannot detect the modification of the {@link linkDataArray} array * or the modification of any link data object. * If you want to add or remove link data from the {@link linkDataArray}, * call the {@link addLinkData} or {@link removeLinkData} methods. * If you want to modify the node a link connects to, call the * {@link setFromKeyForLinkData} and/or {@link setToKeyForLinkData} methods. * If you want to change the membership of a node data in a group, * call the {@link setGroupKeyForNodeData} method. * @category Model */ export class GraphLinksModel extends Model { /** * This constructs an empty GraphLinksModel unless one provides arguments as the initial data array values * for the {@link Model.nodeDataArray} and {@link GraphLinksModel.linkDataArray} properties. * @param nodedataarray - an optional Array containing JavaScript objects to be represented by Nodes. * @param linkdataarray - an optional Array containing JavaScript objects to be represented by Links. */ /** * This constructs an empty GraphLinksModel unless one provides arguments as the initial data array values * for the {@link Model.nodeDataArray} and {@link GraphLinksModel.linkDataArray} properties. * @param nodedataarray - an optional Array containing JavaScript objects to be represented by Nodes. * @param linkdataarray - an optional Array containing JavaScript objects to be represented by Links. * @param init - optional initialization properties. */ constructor(nodedataarray?: Array, linkdataarray?: Array, init?: Partial); /** * This constructs an empty GraphLinksModel unless one provides arguments as the initial data array values * for the {@link Model.nodeDataArray} and {@link GraphLinksModel.linkDataArray} properties. * @param init - optional initialization properties. */ constructor(init?: Partial); /** * Gets or sets a data object that will be copied and added to the model as a new node data each time there * is a link reference (either the "to" or the "from" of a link data) to a node key that does not yet exist in the model. * * The default value is null -- node data is not automatically copied and added to the model * when there is an unresolved reference in a link data. * When adding or modifying a link data if there is a "from" or "to" key value for which {@link Model.findNodeDataForKey} returns null, * it will call {@link Model.copyNodeData} on this property value and {@link Model.addNodeData} on the result. */ get archetypeNodeData(): ObjectData | null; set archetypeNodeData(value: ObjectData | null); /** * Gets or sets the name of the data property that returns * the key of the node data that the link data is coming from. * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the key of the link's source node; * if the second argument is supplied, the function should modify the link data object so that it has that new key * (which may be undefined to refer to no node) as the identifier to the "from" node. * The default value is the name 'from', meaning that it expects the data to have a property named 'from' to refer to the link's source node. * The name must not be null. * If the value is an empty string, * {@link getFromKeyForLinkData} will return undefined for all link data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getFromKeyForLinkData} * @see {@link setFromKeyForLinkData} */ get linkFromKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set linkFromKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * From a link data retrieve a value uniquely identifying the node data * from which this link is connected. * @param linkdata - a JavaScript object represented by a link. * @returns This may return undefined if * the link is not coming from any node. * @see {@link linkFromKeyProperty} * @see {@link setFromKeyForLinkData} */ getFromKeyForLinkData(linkdata: ObjectData): Key; /** * Change the node key that the given link data references as the * source of the link. * @param linkdata - a JavaScript object represented by a link. * @param key - This may be undefined if * the link should no longer come from any node. * @see {@link linkFromKeyProperty} * @see {@link getFromKeyForLinkData} */ setFromKeyForLinkData(linkdata: ObjectData, key: Key): void; /** * Gets or sets the name of the data property that returns * the key of the node data that the link data is going to, * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the key of the link's destination node; * if the second argument is supplied, the function should modify the link data object so that it has that new key * (which may be undefined to refer to no node) as the identifier to the "to" node. * The default value is the name 'to', meaning that it expects the data to have a property named 'to' to refer to the link's destination node. * The name must not be null. * If the value is an empty string, * {@link getToKeyForLinkData} will return undefined for all link data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getToKeyForLinkData} * @see {@link setToKeyForLinkData} */ get linkToKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set linkToKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * From a link data retrieve a value uniquely identifying the node data * to which this link is connected. * @param linkdata - a JavaScript object represented by a link. * @returns This may return undefined if * the link is not going to any node. * @see {@link linkToKeyProperty} * @see {@link setToKeyForLinkData} */ getToKeyForLinkData(linkdata: ObjectData): Key; /** * Change the node key that the given link data references as the * destination of the link. * @param linkdata - a JavaScript object represented by a link. * @param key - This may be undefined if * the link should no longer go to any node. * @see {@link linkToKeyProperty} * @see {@link getToKeyForLinkData} */ setToKeyForLinkData(linkdata: ObjectData, key: Key): void; /** * Gets or sets the name of the data property that returns * the optional parameter naming a "port" element on the node that the link data is connected from. * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the string identifier of the link's source port; * if the second argument is supplied, the function should modify the link data object so that it has that string as the identifier to the "from" port. * The default value is the empty string indicating that one cannot distinguish * different logical connection points for any links. * The name must not be null nor the value of {@link linkFromKeyProperty} or {@link linkToKeyProperty}. * If the value is an empty string, * {@link getFromPortIdForLinkData} will return an empty string for all link data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getFromPortIdForLinkData} * @see {@link setFromPortIdForLinkData} */ get linkFromPortIdProperty(): string | ((a: ObjectData, b?: string) => string); set linkFromPortIdProperty(value: string | ((a: ObjectData, b?: string) => string)); /** * From a link data retrieve a value identifying the port object of the node * from which this link is connected. * @param linkdata - a JavaScript object represented by a link. * @returns This may return the empty string if * there is no particular port parameter information. * @see {@link linkFromPortIdProperty} * @see {@link setFromPortIdForLinkData} */ getFromPortIdForLinkData(linkdata: ObjectData): string; /** * Change the information that the given link data uses to identify the * particular "port" that the link is coming from. * @param linkdata - a JavaScript object represented by a link. * @param portname - This may be the empty string if * the link should no longer be associated with any particular "port". * @see {@link linkFromPortIdProperty} * @see {@link getFromPortIdForLinkData} */ setFromPortIdForLinkData(linkdata: ObjectData, portname: string): void; /** * Gets or sets the name of the data property that returns * the optional parameter naming a "port" element on the node that the link data is connected to. * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the string identifier of the link's destination port; * if the second argument is supplied, the function should modify the link data object so that it has that string as the identifier to the "to" port. * The default value is the empty string indicating that one cannot distinguish * different logical connection points for any links. * The name must not be null nor the value of {@link linkFromKeyProperty} or {@link linkToKeyProperty}. * If the value is an empty string, * {@link getToPortIdForLinkData} will return an empty string for all link data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getToPortIdForLinkData} * @see {@link setToPortIdForLinkData} */ get linkToPortIdProperty(): string | ((a: ObjectData, b?: string) => string); set linkToPortIdProperty(value: string | ((a: ObjectData, b?: string) => string)); /** * From a link data retrieve a value identifying the port object of the node * to which this link is connected. * @param linkdata - a JavaScript object represented by a link. * @returns This may return the empty string if * there is no particular port parameter information. * @see {@link linkToPortIdProperty} * @see {@link setToPortIdForLinkData} */ getToPortIdForLinkData(linkdata: ObjectData): string; /** * Change the information that the given link data uses to identify the * particular "port" that the link is going to. * @param linkdata - a JavaScript object represented by a link. * @param portname - This may be the empty string if * the link should no longer be associated with any particular "port". * @see {@link linkToPortIdProperty} * @see {@link getToPortIdForLinkData} */ setToPortIdForLinkData(linkdata: ObjectData, portname: string): void; /** * Gets or sets the name of the data property that returns * an array of keys of node data that are labels on that link data. * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the array of label node keys for the link; * if the second argument is supplied, the function should modify the link data object so that it holds that Array of node keys as references to label nodes. * The default value is the empty string: '', meaning that the model does not support links owning label nodes. * * The name must not be null. * If the value is an empty string, * {@link getLabelKeysForLinkData} will return an empty array for all link data objects. * You will need to set this property in order to support nodes as link labels. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getLabelKeysForLinkData} * @see {@link setLabelKeysForLinkData} */ get linkLabelKeysProperty(): string | ((a: ObjectData, b?: Array) => Array); set linkLabelKeysProperty(value: string | ((a: ObjectData, b?: Array) => Array)); /** * Gets an Array of node key values that identify node data acting as labels on the given link data. * * This method only works if {@link linkLabelKeysProperty} has been set to something other than an empty string. * @param linkdata - a JavaScript object represented by a link. * @returns an Array of node keys; an empty Array if the property was not present. * @see {@link linkLabelKeysProperty} * @see {@link setLabelKeysForLinkData} * @see {@link addLabelKeyForLinkData} * @see {@link removeLabelKeyForLinkData} */ getLabelKeysForLinkData(linkdata: ObjectData): Array; /** * Replaces an Array of node key values that identify node data acting as labels on the given link data. * * This method only works if {@link linkLabelKeysProperty} has been set to something other than an empty string. * @param linkdata - a JavaScript object represented by a link. * @param arr - an Array of node keys; an empty Array if the property was not present. * @see {@link linkLabelKeysProperty} * @see {@link getLabelKeysForLinkData} * @see {@link addLabelKeyForLinkData} * @see {@link removeLabelKeyForLinkData} */ setLabelKeysForLinkData(linkdata: ObjectData, arr: Array): void; /** * Adds a node key value that identifies a node data acting as a new label node on the given link data. * * This method only works if {@link linkLabelKeysProperty} has been set to something other than an empty string. * @param linkdata - a JavaScript object represented by a link. * @param key - a number or string that is the key of the new label node. * @see {@link removeLabelKeyForLinkData} * @see {@link setLabelKeysForLinkData} */ addLabelKeyForLinkData(linkdata: ObjectData, key: Key): void; /** * Removes a node key value that identifies a node data acting as a former label node on the given link data. * * Removing a reference to a node data from the collection of link label keys * does not automatically remove any node data from the model. * * This method only works if {@link linkLabelKeysProperty} has been set to something other than an empty string. * @param linkdata - a JavaScript object represented by a link. * @param key - a number or string that is the key of the label node being removed from the link. * @see {@link addLabelKeyForLinkData} * @see {@link setLabelKeysForLinkData} */ removeLabelKeyForLinkData(linkdata: ObjectData, key: Key): void; /** * Gets or sets the array of link data objects that correspond to {@link Link}s in the {@link Diagram}. * The initial value is an empty Array. */ get linkDataArray(): Array; set linkDataArray(value: Array); /** * Gets or sets the name of the data property that returns a unique id number or string for each link data object. * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the unique string or number key for that link data object; * if the second argument is supplied, the function should modify the link data object so that it has that string or number as the unique key for that link. * The default value is the empty string, which means the model will not maintain a key property value on link data objects. * The name must not be null. * * When this property has a value of an empty string (the default value), * {@link getKeyForLinkData} will return undefined, and {@link findLinkDataForKey} will always return null. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getKeyForLinkData} */ get linkKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set linkKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * Given a link data object return its unique key: a number or a string. * This returns undefined if there is no key value. * Unless {@link linkKeyProperty} is set to a non-empty string, this model * will not automatically assign unique key values for link data objects. * * It is possible to change the key for a link data object by calling {@link setKeyForLinkData}. * @param linkdata - a JavaScript object represented by a link * @see {@link linkKeyProperty} * @see {@link setKeyForLinkData} * @see {@link findLinkDataForKey} */ getKeyForLinkData(linkdata: ObjectData): Key; /** * Change the unique key of a given link data that is already in this model. * The new key value must be unique -- i.e. not in use by another link data object. * You can call {@link findLinkDataForKey} to check if a proposed new key is already in use. * * If this is called when {@link linkKeyProperty} is the empty string (i.e. its default value), * this method has no effect. * If this is called on a link data object that is not (yet) in this model, * this unconditionally modifies the property to the new key value. * @param linkdata - a JavaScript object represented by a link * @param key * @see {@link linkKeyProperty} * @see {@link getKeyForLinkData} */ setKeyForLinkData(linkdata: ObjectData, key: Key): void; /** * Gets or sets a function that returns a unique id number or string for a link data object. * This function is called by {@link makeLinkDataKeyUnique} * when a link data object is added to the model, either as part of a new * {@link linkDataArray} or by a call to {@link addLinkData}, to make sure the value of * {@link getKeyForLinkData} is unique within the model. * However it will not be called when {@link linkKeyProperty} is the default value, an empty string. * * The value may be null in order to cause {@link makeLinkDataKeyUnique} behave in the standard manner. * (The default value is null.) * You may want to supply a function here in order to make sure all of the automatically generated keys * are in a particular format. * Setting this property after setting {@link linkDataArray} has no real effect until there is a call * to {@link addLinkData}. * * If a link data object is already in the model and you want to change its key value, * call {@link setKeyForLinkData} with a new and unique key. */ get makeUniqueLinkKeyFunction(): ((a: GraphLinksModel, b: ObjectData) => Key) | null; set makeUniqueLinkKeyFunction(value: ((a: GraphLinksModel, b: ObjectData) => Key) | null); /** * Given a number or string, find the link data object in this model * that uses the given value as its unique key. * * Unless {@link linkKeyProperty} is set to a non-empty string, this model * will not automatically assign unique key values for link data objects, * and thus this method will always return null. * @param key - a string or a number. * @returns null if the key is not present in the model, * or if the key is null or undefined or not a string or number. * @see {@link containsLinkData} * @see {@link getKeyForLinkData} */ findLinkDataForKey(key: Key): ObjectData | null; /** * This method is called when a link data object is added to the model to make sure that * {@link getKeyForLinkData} returns a unique key value. * * The key value should be unique within the set of data managed by this model: * {@link linkDataArray}. * If the key is already in use, this will assign an unused number to the * {@link linkKeyProperty} property on the data. * * If you want to customize the way in which link data gets a unique key, * you can set the {@link makeUniqueKeyFunction} functional property. * * If the link data object is already in the model and you want to change its key value, * call {@link setKeyForLinkData} and give it a new unique key value. * @param linkdata - a JavaScript object represented by a link */ makeLinkDataKeyUnique(linkdata: ObjectData): void; /** * Decide if a given link data object is in this model, using reference equality. * * If you do not have a reference to the particular data object that is in the {@link linkDataArray}, * you may need to search for it by iterating through that Array, or (more likely), * by finding the desired {@link Link} in a {@link Diagram} and getting that link's {@link Panel.data}. * * Note that because link data are not assumed to be have a unique key property * they cannot be found using an index that this model would maintain. * However you may choose to provide such a property on the link data objects * and maintain your own index. * @param linkdata - a JavaScript object represented by a link; if null, this predicate will return false * @see {@link addLinkData} * @see {@link removeLinkData} */ containsLinkData(linkdata: ObjectData | null): boolean; /** * When you want to add a link to the diagram, call this method with a new data object. * This will add that data to the {@link linkDataArray} and * notify all listeners that a new link data object has been inserted into the collection. * * Presumably the link data object will already have its "from" and "to" node key references set, * but it is also possible to set them after the link data is in the model * by calling {@link setFromKeyForLinkData} and {@link setToKeyForLinkData}. * * This operation does nothing if the link data is already part of this model's {@link linkDataArray}. * @param linkdata - a JavaScript object represented by a link. * @see {@link removeLinkData} */ addLinkData(linkdata: ObjectData): void; /** * Add to this model all of the link data held in an Array or in an {@link Iterable} of link data objects. * @param coll - a collection of link data objects to add to the {@link linkDataArray} */ addLinkDataCollection(coll: Iterable | Array): void; /** * When you want to remove a link from the diagram, call this method with an existing link data object. * This will remove that data object from the {@link linkDataArray} and * notify all listeners that a link data object has been removed from the collection. * * If you do not have a reference to the particular data object that is in the {@link linkDataArray}, * you may need to search for it by iterating through that Array, or (more likely), * by finding the desired {@link Link} in a {@link Diagram} and getting that link's {@link Panel.data}. * * Removing a link data from a model does not automatically remove * any associated label node data from the model. * * This operation does nothing if the link data is not present in the {@link linkDataArray}. * @param linkdata - a JavaScript object represented by a link. * @see {@link addLinkData} */ removeLinkData(linkdata: ObjectData): void; /** * Remove from this model all of the link data held in an Array or in an {@link Iterable} of link data objects. * @param coll - a collection of link data objects to remove from the {@link linkDataArray} */ removeLinkDataCollection(coll: Iterable | Array): void; /** * Take an Array of link data objects and update {@link linkDataArray} without replacing * the Array and without replacing any existing link data objects that are identified by key. * This depends on {@link linkKeyProperty} being a non-empty string. * * For link data objects that have the same key value, this makes calls to {@link setDataProperty} * to update the existing link data object. * For new keys, this calls {@link cloneDeep} to copy the data and then {@link addLinkData} to add a new link to the model. * For existing links that have keys that are not present in the given Array, * this calls {@link removeLinkData} to remove the existing link from the model. * * This method is typically used when GoJS is being used within an application that is maintaining state * related to the diagram model. When state is updated, this method can be called to keep the GoJS model synchronized. * Any updates to the data should use new references since this method will use reference equality to check * if a link data object needs to be updated. * * This method does not conduct a transaction. * @param arr * @since 2.1 */ mergeLinkDataArray(arr: Array): void; /** * Gets or sets a function that makes a copy of a link data object. * * You may need to set this property in order to ensure that a copied {@link Link} is bound * to data that does not share certain data structures between the original link data and the copied link data. * This property value may be null in order to cause {@link copyLinkData} to make a shallow copy of a JavaScript Object. * The default value is null. */ get copyLinkDataFunction(): ((a: ObjectData, b: GraphLinksModel) => ObjectData) | null; set copyLinkDataFunction(value: ((a: ObjectData, b: GraphLinksModel) => ObjectData) | null); /** * Make a copy of a link data object. * This uses the value of {@link copyLinkDataFunction} to actually perform the copy, * unless it is null, in which case this method just makes a shallow copy of the JavaScript Object. * * This does not modify the model -- the returned data object is not added to this model. * This assumes that the data's constructor can be called with no arguments. * This also makes sure there is no reference to either the "from" or the "to" node of the original data. * @param linkdata - a JavaScript object represented by a link. * @see {@link addLinkData} */ copyLinkData(linkdata: ObjectData): ObjectData; /** * Gets or sets the name of the boolean property on node data that indicates * whether the data should be represented as a group of nodes and links or as a simple node. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return true if the node data object should be represented by a Group and false otherwise. * At the current time the function will not be called to change whether the node is a group or not. * The default value is the name 'isGroup', meaning that it expects the data to have a property named 'isGroup' on those node data objects that should be represented by Groups. * * The value must not be null. * If the value is an empty string, * {@link isGroupForNodeData} will return false for all node data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. */ get nodeIsGroupProperty(): string | ((a: ObjectData, b?: boolean) => boolean); set nodeIsGroupProperty(value: string | ((a: ObjectData, b?: boolean) => boolean)); /** * See if the given node data should be represented as a group or as a simple node. * * This value must not change as long as the node data is part of the model. * At the current time there is no `setIsGroupForNodeData` method. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link nodeIsGroupProperty} */ isGroupForNodeData(nodedata: ObjectData): boolean; /** * Gets or sets the name of the property on node data that specifies * the string or number key of the group data that "owns" that node data. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return the string or number key for the group data object of which the given data object is a member; * if the second argument is supplied, the function should modify the node data object so that it has that new key * (which may be undefined to refer to no node) as the containing group key for that node. * The default value is the name 'group', meaning that it expects the data to have a property named 'group' to refer to any containing group. * * The value must not be null. * If the value is an empty string, * {@link getGroupKeyForNodeData} will return undefined for all node data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getGroupKeyForNodeData} * @see {@link setGroupKeyForNodeData} */ get nodeGroupKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set nodeGroupKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * If there is a container group for the given node data, return the group's key. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @returns This returns undefined if there is no containing group data. * @see {@link nodeGroupKeyProperty} * @see {@link setGroupKeyForNodeData} */ getGroupKeyForNodeData(nodedata: ObjectData): Key; /** * Change the container group for the given node data, given a key for the new group. * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @param key - This may be undefined if there should be no containing group data. * @see {@link nodeGroupKeyProperty} * @see {@link getGroupKeyForNodeData} */ setGroupKeyForNodeData(nodedata: ObjectData, key: Key): void; /** * This override also makes sure any copied node data does not have a reference to the containing group. * @virtual * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link Model.copyNodeData} */ copyNodeData(nodedata: ObjectData): ObjectData | null; /** * This override changes the value of some property of a node data, a link data, or an item data, given a string naming the property * and the new value, in a manner that can be undone/redone and that automatically updates any bindings. * This override handles link data as well as node data. * * This gets the old value of the property; if the value is the same as the new value, no side-effects occur. * @virtual * @param data - a JavaScript object typically the value of a {@link Panel.data} and represented by a Node, Link, Group, simple Part, * or item in a {@link Panel.itemArray}; or this model's {@link modelData}. * @param propname - a string that is not null or the empty string. * @param val - the new value for the property. * @see {@link Model.setDataProperty} */ setDataProperty(data: ObjectData, propname: string, val: any): void; /** * This override is similar to Object.assign, * but safely calls {@link setDataProperty} for each property other than a key property. * @param data - a data object * @param props - an Object holding various properties whose values are to be assigned to the DATA object */ assignAllDataProperties(data: ObjectData, props: ObjectData): void; /** * Gets or sets the name of the data property that returns a string naming that data's category, * The value may also be a function taking two arguments, where the first argument will be a link data object. * If the second argument is not supplied, the function should return the category name; * if the second argument is supplied, the function should modify the link data object so that it has that new category name. * The default value is the name 'category', meaning that it expects the data to have a property named 'category' if it cares to name the category for the Link. * This is used by the diagram to distinguish between different kinds of links. * The name must not be null. * If the value is an empty string, * {@link getCategoryForLinkData} will return an empty string for all link data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getCategoryForLinkData} * @see {@link setCategoryForLinkData} */ get linkCategoryProperty(): string | ((a: ObjectData, b?: string) => string); set linkCategoryProperty(value: string | ((a: ObjectData, b?: string) => string)); /** * Find the category of a given link data, a string naming the link template * that the {@link Diagram} should use to represent the link data. * @param linkdata - a JavaScript object represented by a link. * @see {@link linkCategoryProperty} * @see {@link setCategoryForLinkData} */ getCategoryForLinkData(linkdata: ObjectData): string; /** * Change the category of a given link data, a string naming the link template * that the {@link Diagram} should use to represent the link data. * * Changing the link template for a link data will cause the existing {@link Link} * to be removed from the {@link Diagram} and be replaced with a new {@link Link} * created by copying the new link template and applying any data-bindings. * Note that the new template must be an instance of the same class as the original link. * Thus one cannot change the category of a link from an instance of {@link Link} * to an instance of a subclass of Link, nor vice-versa. * @param linkdata - a JavaScript object represented by a link. * @param cat - Must not be null. * @see {@link linkCategoryProperty} * @see {@link getCategoryForLinkData} */ setCategoryForLinkData(linkdata: ObjectData, cat: string): void; } /** * TreeModels support tree-structured graphs of nodes and links. * Each node can have at most one "tree parent"; cycles are not permitted. * The reference to the parent node's key is a property of the child node data. * * TreeModels, unlike {@link GraphLinksModel}s, do not support arbitrary link relationships between nodes, * nor is there a separate link data object for each parent-child relationship. * Furthermore there is no support for grouping or label nodes. * * The {@link nodeParentKeyProperty} property names the property on the node data whose value * is the key of the "tree parent" node. * The default value for this property is "parent". * * For example, one can define a graph consisting of one parent node with two child nodes: * ```js * model.nodeDataArray = [ * { key: "Alpha" }, * { key: "Beta", parent: "Alpha" }, * { key: "Gamma", parent: "Alpha" } * ]; * ``` * * If you need to show a more complicated graph structure than a tree, use a {@link GraphLinksModel}. * If you want to have multiple links between the same pair of nodes, * or if you want to associate more information with each link and cannot put the information on the child node, * you will need to have a separate link data object for each link, * and that would require the use of {@link GraphLinksModel}. * @category Model */ export class TreeModel extends Model { /** * This constructs an empty TreeModel unless one provides arguments as the initial data array values * @param nodedataarray - an optional Array containing JavaScript objects to be represented by {@link Part}s. * @param init - Optional initialization properties. */ constructor(nodedataarray?: Array, init?: Partial); /** * for the {@link Model.nodeDataArray} property. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Gets or sets the name of the property on node data that specifies * the string or number key of the node data that acts as the "parent" for this "child" node data. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return the string or number key for the parent node data object of which the given data object is a child; * if the second argument is supplied, the function should modify the node data object so that it has that new key * (which may be undefined to refer to no node) as the parent key for that node.. * The default value is the name 'parent', meaning that it expects the data to have a property named 'parent' if the node wants to refer to the parent node by its key. * The value must not be null nor an empty string. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getParentKeyForNodeData} * @see {@link setParentKeyForNodeData} */ get nodeParentKeyProperty(): string | ((a: ObjectData, b?: Key) => Key); set nodeParentKeyProperty(value: string | ((a: ObjectData, b?: Key) => Key)); /** * If there is a parent node for the given node data, return the parent's key. * @param nodedata - a JavaScript object represented by a node. * @returns This returns undefined if there is no parent node data object. * @see {@link nodeParentKeyProperty} * @see {@link setParentKeyForNodeData} */ getParentKeyForNodeData(nodedata: ObjectData): Key; /** * Change the parent node for the given node data, given a key for the new parent, or undefined if there should be no parent. * @param nodedata - a JavaScript object represented by a node. * @param key - This may be undefined if there should be no parent node data. * @see {@link nodeParentKeyProperty} * @see {@link getParentKeyForNodeData} */ setParentKeyForNodeData(nodedata: ObjectData, key: Key): void; /** * Gets or sets the name of the data property that returns a string describing that node data's parent link's category. * The value may also be a function taking two arguments, where the first argument will be a node data object. * If the second argument is not supplied, the function should return the category name for any parent link; * if the second argument is supplied, the function should modify the node data object so that its parent link has that new category name. * The default value is the name 'parentLinkCategory'. * This is used by the diagram to distinguish between different kinds of links. * The name must not be null. * If the value is an empty string, * {@link getParentLinkCategoryForNodeData} will return an empty string for all node data objects. * * If you want to set this property you must do so before using the model, and especially before you assign {@link Diagram.model}. * Note that functions cannot be serialized into JSON-formatted text, so if you are using {@link toJson} and {@link Model.fromJson}, * and if you want this property to be a function, you will need to assign this property to your desired function * immediately after creating the model, including when it is created by {@link Model.fromJson}. * @see {@link getParentLinkCategoryForNodeData} * @see {@link setParentLinkCategoryForNodeData} */ get parentLinkCategoryProperty(): string | ((a: ObjectData, b?: string) => string); set parentLinkCategoryProperty(value: string | ((a: ObjectData, b?: string) => string)); set linkCategoryProperty(value: string | ((a: ObjectData, b?: string) => string)); /** * Find the category for the parent link of a given child node data, a string naming the link template * that the {@link Diagram} should use to represent the link. * @param childdata - a JavaScript object represented by a node data. * @see {@link parentLinkCategoryProperty} * @see {@link setParentLinkCategoryForNodeData} */ getParentLinkCategoryForNodeData(childdata: ObjectData): string; /** * Change the category for the parent link of a given child node data, a string naming the link template * that the {@link Diagram} should use to represent the link. * * Changing the link template will cause any existing {@link Link} * to be removed from the {@link Diagram} and replaced with a new {@link Link} * created by copying the new link template and applying any data-bindings. * Note that the new template must be an instance of the same class as the original link. * Thus one cannot change the category of a link from an instance of {@link Link} * to an instance of a subclass of Link, nor vice-versa. * @param childdata - a JavaScript object represented by a node data. * @param cat - Must not be null. * @see {@link parentLinkCategoryProperty} * @see {@link getParentLinkCategoryForNodeData} */ setParentLinkCategoryForNodeData(childdata: ObjectData, cat: string): void; /** * This override also makes sure any copied node data does not have a reference to a parent node. * @virtual * @param nodedata - a JavaScript object represented by a node, group, or non-link. * @see {@link Model.copyNodeData} */ copyNodeData(nodedata: ObjectData): ObjectData | null; /** * This override changes the value of some property of a node data or an item data, given a string naming the property * and the new value, in a manner that can be undone/redone and that automatically updates any bindings. * * This gets the old value of the property; if the value is the same as the new value, no side-effects occur. * @virtual * @param data - a JavaScript object typically the value of a {@link Panel.data} and represented by a Node, Link, Group, simple Part, * or item in a {@link Panel.itemArray}; or this model's {@link modelData}. * @param propname - a string that is not null or the empty string. * @param val - the new value for the property. * @see {@link Model.setDataProperty} */ setDataProperty(data: ObjectData, propname: string, val: any): void; } /** * This enumeration specifies how nodes should be spaced in the ring. * Used for {@link CircularLayout.arrangement}. * @since 3.0 * @category Layout */ export declare enum CircularArrangement { /** * The spacing between the idealized boundaries of the nodes is constant. */ ConstantSpacing = 0, /** * The distance between the centers of the nodes is constant. */ ConstantDistance = 1, /** * The angular distance between the nodes is constant. */ ConstantAngle = 2, /** * The vertices are arranged as close together as possible considering the {@link CircularLayout.spacing}, * assuming the nodes are rectangular. */ Packed = 3 } /** * This enumeration specifies the direction in which the nodes fill the ring. * Used for {@link CircularLayout.direction}. * @since 3.0 * @category Layout */ export declare enum CircularDirection { /** * Rings are filled clockwise. */ Clockwise = 10, /** * Rings are filled counterclockwise. */ Counterclockwise = 11, /** * The ring is filled by alternating sides; the second node is counterclockwise from the first node. */ BidirectionalLeft = 12, /** * The ring is filled by alternating sides; the second node is clockwise from the first node. */ BidirectionalRight = 13 } /** * This enumeration specifies how to sort the nodes. * Used for {@link CircularLayout.sorting}. * @since 3.0 * @category Layout */ export declare enum CircularSorting { /** * Nodes are arranged in the order given. */ Forwards = 20, /** * Nodes are arranged in the reverse of the order given. */ Reverse = 21, /** * Nodes are sorted using the {@link CircularLayout.comparer}, in ascending order. */ Ascending = 22, /** * Nodes are sorted using the {@link CircularLayout.comparer}, in reverse ascending (descending) order. */ Descending = 23, /** * Nodes are ordered to reduce link crossings. */ Optimized = 24 } /** * This enumeration specifies a method for finding the size of a node. * Used for {@link CircularLayout.nodeDiameterFormula}. * @since 3.0 * @category Layout */ export declare enum CircularNodeDiameterFormula { /** * The effective diameter is sqrt(width^2+height^2); * The corners of square nodes will touch at 45 degrees when {@link CircularLayout.spacing} is 0. */ Pythagorean = 30, /** * The effective diameter is either the width or height of the node, whichever is larger; * This will cause circular nodes to touch when {@link CircularLayout.spacing} is 0; * This is ideal when the nodes are circular. */ Circular = 31 } /** * This layout positions nodes in a circular arrangement. * There are several samples that use CircularLayout. * The layout cannot guarantee that it provides optimal positioning of nodes when trying to minimize link crossings. *

* If you want to experiment interactively with most of the properties, try the Circular Layout sample. * See samples that make use of CircularLayout in the samples index. * * This layout makes use of a {@link LayoutNetwork} of * {@link CircularVertex}es and {@link CircularEdge}s that normally * correspond to the {@link Node}s and {@link Link}s of the {@link Diagram}. * @category Layout */ export class CircularLayout extends Layout { /** * Constructs a {@link CircularLayout} with no {@link Layout.network} * and with no owning {@link Layout.diagram}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Create a new {@link LayoutNetwork} of {@link CircularVertex}es and {@link CircularEdge}s. * @returns a new {@link LayoutNetwork}. */ createNetwork(): CircularNetwork; /** * Assign the positions of the vertexes in the network. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ doLayout(coll: Diagram | Group | Iterable): void; /** * Position each {@link Node} according to the Vertex position, and then position the {@link Link}s. * * You should not call this method -- it is a "protected virtual" method. */ protected commitLayout(): void; /** * Commit the position of all vertex nodes. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitNodes(): void; /** * Commit the position and routing of all edge links. * This is called by {@link commitLayout}. * This is only called if {@link Layout.isRouting} is true. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitLinks(): void; /** * Gets or sets the horizontal radius of the elliptical arrangement. * * The default value is NaN. * NaN indicates that the {@link spacing} will determine the size of the ring. * If {@link spacing} is also NaN, the effective spacing will be 6. * If {@link spacing} is a number, the effective radius will be > radius if and only if * the spacing between elements would otherwise be less than spacing. * The specified value for {@link radius} will be ignored if {@link arrangement} === {@link CircularArrangement.Packed}. * This property must always be positive or NaN. */ get radius(): number; set radius(value: number); /** * Gets or sets the ratio of the arrangement's height to its width * (1 for a circle, >1 for a vertically elongated ellipse). * * This is 1 by default. * The value must be a positive number. * * Modifying this value changes the height, but keeps the width and the {@link radius} constant. */ get aspectRatio(): number; set aspectRatio(value: number); /** * Gets or sets the angle (in degrees, clockwise from the positive side of the X axis) of the first element. * * The default value is 0. */ get startAngle(): number; set startAngle(value: number); /** * Gets or sets the absolute angle (in degrees) between the first and last node. * * The default value is 360. * The value must be greater than zero and less than or equal to 360. * If it is not in this range, it will be automatically set to 360. * * Whether the arrangement is clockwise or counterclockwise does not depend on the sign of this value. * The direction can be controlled by setting {@link direction}. * If 360 is the specified value, the actual value will be less to keep the first and last * elements from overlapping, and the spacing between the first and last nodes will be determined * the same way as for all other adjacent nodes. */ get sweepAngle(): number; set sweepAngle(value: number); /** * Gets or sets how the nodes are spaced. * If {@link arrangement} === {@link CircularArrangement.Packed}, * the specified {@link radius} will be ignored. * * The default value is {@link CircularArrangement.ConstantSpacing}. */ get arrangement(): CircularArrangement; set arrangement(value: CircularArrangement); /** * Gets or sets whether the nodes are arranged clockwise or counterclockwise. * * The default value is {@link CircularDirection.Clockwise}. */ get direction(): CircularDirection; set direction(value: CircularDirection); /** * Gets or sets if and how the nodes are sorted. * * {@link CircularSorting.Forwards} indicates that the nodes are arranged in the order the layout gets them. * {@link CircularSorting.Reverse} indicates that the nodes are arranged in the reverse order that the layout gets them. * {@link CircularSorting.Ascending} and {@link CircularSorting.Descending} indicate that the nodes * will be sorted using the {@link comparer}. * {@link CircularSorting.Optimized} indicates that the nodes will be arranged to minimize link crossings. * * The default value is {@link CircularSorting.Optimized}. */ get sorting(): CircularSorting; set sorting(value: CircularSorting); /** * Gets or sets the comparer which sorts the data when {@link sorting} is * set to {@link CircularSorting.Ascending} or {@link CircularSorting.Descending}. * * The default function compares the {@link Part.text} values of the vertexes' {@link LayoutVertex.node}s. */ get comparer(): ((a: CircularVertex, b: CircularVertex) => number); set comparer(value: ((a: CircularVertex, b: CircularVertex) => number)); /** * Gets or sets the distance between nodes (if {@link radius} is NaN) * or the minimum distance between nodes (if {@link radius} is a number). * * The default value is 6. * The value may be NaN. * * If {@link spacing} is NaN, there is no minimum spacing, allowing nodes to overlap, * unless {@link radius} is NaN, * in which case the effective spacing will be 6 to determine an effective radius. * If {@link spacing} is a number but {@link radius} isn't, * the effective spacing will be spacing, and this will determine the effective radius. * If both {@link spacing} and {@link radius} are numbers, * the effective radius will be at least {@link radius}, * but may be larger so that the minimum spacing between nodes is {@link spacing}. */ get spacing(): number; set spacing(value: number); /** * Specifies how the diameter of nodes will be calculated. * When a node is not circular, it is not clear what its diameter is. * * The default is {@link CircularNodeDiameterFormula.Pythagorean}. */ get nodeDiameterFormula(): CircularNodeDiameterFormula; set nodeDiameterFormula(value: CircularNodeDiameterFormula); /** * This read-only property is the effective X radius that may have been calculated by the layout. */ get actualXRadius(): number; /** * This read-only property is the effective Y radius that may have been calculated by the layout. */ get actualYRadius(): number; /** * This read-only property is the effective spacing that may have been calculated by the layout. */ get actualSpacing(): number; /** * This read-only property is the coordinates of the center of the laid-out ellipse immediately after the layout. */ get actualCenter(): Point; /** * @deprecated See {@link CircularArrangement.ConstantSpacing}. */ static readonly ConstantSpacing = CircularArrangement.ConstantSpacing; /** * @deprecated See {@link CircularArrangement.ConstantDistance}. */ static readonly ConstantDistance = CircularArrangement.ConstantDistance; /** * @deprecated See {@link CircularArrangement.ConstantAngle}. */ static readonly ConstantAngle = CircularArrangement.ConstantAngle; /** * @deprecated See {@link CircularArrangement.Packed}. */ static readonly Packed = CircularArrangement.Packed; /** * @deprecated See {@link CircularDirection.Clockwise}. */ static readonly Clockwise = CircularDirection.Clockwise; /** * @deprecated See {@link CircularDirection.Counterclockwise}. */ static readonly Counterclockwise = CircularDirection.Counterclockwise; /** * @deprecated See {@link CircularDirection.BidirectionalLeft}. */ static readonly BidirectionalLeft = CircularDirection.BidirectionalLeft; /** * @deprecated See {@link CircularDirection.BidirectionalRight}. */ static readonly BidirectionalRight = CircularDirection.BidirectionalRight; /** * @deprecated See {@link CircularSorting.Forwards}. */ static readonly Forwards = CircularSorting.Forwards; /** * @deprecated See {@link CircularSorting.Reverse}. */ static readonly Reverse = CircularSorting.Reverse; /** * @deprecated See {@link CircularSorting.Ascending}. */ static readonly Ascending = CircularSorting.Ascending; /** * @deprecated See {@link CircularSorting.Descending}. */ static readonly Descending = CircularSorting.Descending; /** * @deprecated See {@link CircularSorting.Optimized}. */ static readonly Optimized = CircularSorting.Optimized; /** * @deprecated See {@link CircularNodeDiameterFormula.Pythagorean}. */ static readonly Pythagorean = CircularNodeDiameterFormula.Pythagorean; /** * @deprecated See {@link CircularNodeDiameterFormula.Circular}. */ static readonly Circular = CircularNodeDiameterFormula.Circular; } /** * This class represents an abstract graph of {@link CircularVertex}es and {@link CircularEdge}s * that can be constructed based on the {@link Node}s and {@link Link}s of a {@link Diagram} * so that the {@link CircularLayout} can operate independently of the diagram until it * is time to commit any node positioning or link routing. * * This class inherits from {@link LayoutNetwork}. * @category Layout * @unindexed */ export class CircularNetwork extends LayoutNetwork { constructor(layout: CircularLayout); } /** * This holds {@link CircularLayout}-specific information about {@link Node}s. * * This class inherits from {@link LayoutVertex}. * @category Layout * @unindexed */ export class CircularVertex extends LayoutVertex { constructor(network: CircularNetwork); /** * Gets or sets the value used as the vertex's diameter. * * By default the value depends on the {@link CircularLayout.arrangement} property. * Any computed value is cached, to avoid unnecessary expensive computations. */ get diameter(): number; set diameter(value: number); /** * Gets or sets the value used as the vertex's angle. */ get actualAngle(): number; set actualAngle(value: number); } /** * This holds {@link CircularLayout}-specific information about {@link Link}s. * * This class inherits from {@link LayoutEdge}. * @category Layout * @unindexed */ export class CircularEdge extends LayoutEdge { constructor(network: CircularNetwork); } /** * Force-directed layout treats the graph as if it were a system of physical bodies * with repulsive electrical, attractional gravitational, and spring forces acting on them and between them. * * Electrical forces come both from the field at the vertex's location as well as from neighboring vertexes and are quadratic by distance. * Gravitational forces come from the field at the vertex's location and are constant. * Spring forces are only exerted between two different vertexes that are connected by an edge and are linear by distance. * * The electrical forces on a vertex are the sum of the electrical charge times the electrical field at that location * ({@link electricalCharge}, {@link electricalFieldX}, {@link electricalFieldY}) * and the electrical forces of all nearby vertexes divided by the square of the distance between them. * You can easily assign the electrical charge for all vertexes by assigning {@link defaultElectricalCharge}. * By default there is no electrical field, so all forces are due to nearby charged vertexes. * For efficiency, {@link infinityDistance} determines a cut-off distance between vertexes for which to consider any influence. * * The gravitational forces on a vertex are the sum of the gravitational mass times the gravitational field at that location * ({@link gravitationalMass}, {@link gravitationalFieldX}, {@link gravitationalFieldY}). * You can easily assign the gravitational mass for all vertexes by assigning {@link defaultGravitationalMass}. * By default there is no gravitational field. * * The spring forces on a vertex are only exerted by the edges connecting it with other vertexes. * The force along an edge is the stiffness of the spring times the difference of the distance between the vertexes and the nominal length of the spring * ({@link springStiffness}, {@link springLength}) divided by the distance between the vertexes. * When the distance is less than the nominal length, the force pushes the vertexes apart; when the distance is greater, the force pulls them together. * You can easily assign the spring length and stiffness for all edges by assigning {@link defaultSpringLength} and {@link defaultSpringStiffness}. * * When the distance between two vertexes is less than one unit, this uses a random number generator to decide which direction the forces should go. * For layouts that start with all of the vertexes at the same location, this results in potentially dramatically different results. * Set {@link randomNumberGenerator} to null in order to produce reproducible results given the same initial vertex locations. * * The algorithm seeks a configuration of the bodies with locally minimal energy, * i.e. vertex positions such that the sum of the forces on each vertex is zero. * This is achieved by repeatedly computing the forces on each vertex, moving them, and repeating. * Computations stop when no vertex moves more than {@link epsilonDistance} or when {@link maxIterations} have happened. * * The layout cannot guarantee that it provides optimal positioning of nodes. * Nodes will normally not overlap each other, but when there is a dense interconnectivity overlaps might not be avoidable. *

* If you want to experiment interactively with most of the properties, try the Force Directed Layout sample. * See samples that make use of ForceDirectedLayout in the samples index. *

* * This layout makes use of a {@link LayoutNetwork} of * {@link ForceDirectedVertex}es and {@link ForceDirectedEdge}s that normally * correspond to the {@link Node}s and {@link Link}s of the {@link Diagram}. * @category Layout */ export class ForceDirectedLayout extends Layout { /** * Constructs a {@link ForceDirectedLayout} with no {@link Layout.network} * and with no owning {@link Layout.diagram}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Create a new {@link LayoutNetwork} of {@link ForceDirectedVertex}es and {@link ForceDirectedEdge}s. * @returns a new {@link LayoutNetwork}. */ createNetwork(): ForceDirectedNetwork; /** * Perform the force-directed layout. * * If there is no {@link Layout.network}, this calls {@link makeNetwork} to create a {@link LayoutNetwork} from the given collection of Parts. * This removes any reflexive edges in the network, since they should be ignored. * * For each vertex this calls and remembers the result of {@link electricalCharge} as the {@link ForceDirectedVertex.charge} * and the result of {@link gravitationalMass} as the {@link ForceDirectedVertex.mass}. * * For each edge this calls and remembers the result of {@link springStiffness} as the {@link ForceDirectedEdge.stiffness} * and the result of {@link springLength} as the {@link ForceDirectedEdge.length}. * * This then iterates, updating the position of each vertex according to the forces upon it, * until reaching {@link maxIterations} or until no vertex moves more than about {@link epsilonDistance}. * * Finally this calls {@link Layout.updateParts} to commit the Node positions from the vertex positions. * {@link Layout.updateParts} calls {@link commitLayout} within a transaction. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s */ doLayout(coll: Diagram | Group | Iterable): void; /** * Determines whether a spring-based prelayout should be performed before the main force-directed layout operation. * In general this should occur when the network has not already been laid out either by ForceDirectedLayout or some other algorithm. * * By default, this function will return true if any node in the network has a NaN position, likely meaning it has not * been positioned yet, or if a large number of nodes in the network in the network overlap. This function can be overriden * to provide custom logic for determining whether a prelayout should be performed. * * @virtual * @since 3.0 */ needsPrelayout(): boolean; /** * Find any associated objects to be positioned along with the {@link LayoutVertex.node}. * * This method is called for each vertex in the network, when {@link comments} is true. * The standard behavior is to look for {@link Node}s whose {@link Part.category} * is "Comment" and that refer to the {@link LayoutVertex.node}. * By default this method will not be called unless you set {@link comments} to true. * * You may want to override this method in order to customize how any * associated objects are found and how a new {@link ForceDirectedVertex} * and {@link ForceDirectedEdge} * may be added to the network to represent the (balloon?) comment. * This method sets the new vertex's {@link ForceDirectedVertex.charge} * to the value of {@link defaultCommentElectricalCharge}, * and sets the new edge's {@link ForceDirectedEdge.length} * to the value of {@link defaultCommentSpringLength}. * @virtual * @param v */ addComments(v: ForceDirectedVertex): void; /** * (undocumented) * Move the vertex by its {@link ForceDirectedVertex.forceX} and {@link ForceDirectedVertex.forceY}. * Return the square of the distance moved. * This can be overridden in order to constrain the vertex's actual movement. * @virtual * @param v * @returns square of distance moved */ moveVertex(v: ForceDirectedVertex): number; /** * Determines whether the layout should calculate electrical forces between two given vertexes, * for example, for layouts that should stop moving vertexes once they no longer physically overlap. * * By default, this always returns true. * * @param {ForceDirectedVertex} v1 * @param {ForceDirectedVertex} v2 * @since 3.0 */ shouldInteract(v1: ForceDirectedVertex, v2: ForceDirectedVertex): boolean; /** * Maybe move a vertex that {@link isFixed}. * This is called each iteration on each such vertex. * By default this does nothing. * @virtual * @param v */ moveFixedVertex(v: ForceDirectedVertex): void; /** * Set the fromSpot and toSpot on each Link, position each Node according * to the vertex position, and then position/route the Links. * * This calls the {@link commitNodes} and {@link commitLinks} methods, the latter only if {@link isRouting} is true. * You should not call this method -- it is a "protected virtual" method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. */ protected commitLayout(): void; /** * Commit the position of all nodes. * * This is called by {@link commitLayout}. * See also {@link commitLinks}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitNodes(): void; /** * Routes the links. * * This is called by {@link commitLayout}. * This is only called if {@link Layout.isRouting} is true. * See also {@link commitNodes}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitLinks(): void; /** * Returns the stiffness of the spring representing an edge. * * The spring force between two vertexes connected by an edge is linearly proportional by distance * to the difference between the {@link springLength} and the distance. * When the distance is greater than the length, the force pulls the vertexes closer to each other. * When the distance is less than the length, the force pushes them apart. * * The two vertexes connected by the edge E are acted upon by a force of proportional to * `springStiffness(E) * (getNodeDistance(E.fromVertex, E.toVertex) - springLength(E))` divided by the distance between the vertexes. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param e * @returns Returns the stiffness of the edge representing a link, * the value of {@link ForceDirectedEdge.stiffness} if it's a number, * or else the value of {@link defaultSpringStiffness}. */ springStiffness(e: ForceDirectedEdge): number; /** * Returns the length of the spring representing an edge. * The two vertexes connected by the edge E are acted upon by a force of proportional to * `springStiffness(E) * (getNodeDistance(E.fromVertex, E.toVertex) - springLength(E))` divided by the distance between the vertexes. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param e * @returns Returns the length of the edge representing a link, * the value of {@link ForceDirectedEdge.length} if it's a number, * or else the value of {@link defaultSpringLength}. */ springLength(e: ForceDirectedEdge): number; /** * Returns the charge of the vertex, * the value of {@link ForceDirectedVertex.charge} if it's a number, * or else the value of {@link defaultElectricalCharge}. * * The electrical forces between two vertexes decrease by the square of the distance between them. * Vertexes that are more than {@link infinityDistance} apart are assumed to have no electrical charge effect on each other. * * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param v */ electricalCharge(v: ForceDirectedVertex): number; /** * Returns the electrical field in the X direction acting on a vertex at the given point. * By default there is no electrical field at any location. * * Used to define an external electrical field at a point independent of the vertex charges. * A vertex L is acted upon by a force in the X direction of proportional to * `electricalFieldX(L.center.x, L.center.y) * electricalCharge(L)`. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param x * @param y * @returns the default implementation returns zero. */ electricalFieldX(x: number, y: number): number; /** * Returns the electrical field in the Y direction acting on a vertex at the given point. * By default there is no electrical field at any location. * * Used to define an external electrical field at a point independent of the vertex charges. * A vertex L is acted upon by a force in the Y direction of proportional to * `electricalFieldY(L.center.x, L.center.y) * electricalCharge(L)`. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param x * @param y * @returns the default implementation returns zero. */ electricalFieldY(x: number, y: number): number; /** * Returns the mass of the vertex, * the value of {@link ForceDirectedVertex.mass} if it's a number, * or else the value of {@link defaultGravitationalMass}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param v */ gravitationalMass(v: ForceDirectedVertex): number; /** * This returns the gravitational field in the X direction acting on a vertex at the given point. * By default there is no gravitational field at any location. * * Used to define an external gravitational field at a point independent of the vertex masses. * A vertex L is acted upon by a force in the X direction of proportional to * `gravitationalFieldX(L.center.x, L.center.y) * gravitationalMass(L)`. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param x * @param y * @returns the default implementation returns zero. */ gravitationalFieldX(x: number, y: number): number; /** * This returns the gravitational field in the Y direction acting on a vertex at the given point. * By default there is no gravitational field at any location. * * Used to define an external gravitational field at a point independent of the vertex masses. * A vertex L is acted upon by a force in the Y direction of proportional to * `gravitationalFieldY(L.center.x, L.center.y) * gravitationalMass(L)`. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param x * @param y * @returns the default implementation returns zero. */ gravitationalFieldY(x: number, y: number): number; /** * This predicate returns true if the vertex should not be moved * by the layout algorithm but still have an effect on nearby and connected vertexes. * The default implementation returns {@link ForceDirectedVertex.isFixed}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param v * @returns returns true if the node should not be moved by the layout algorithm. */ isFixed(v: ForceDirectedVertex): boolean; /** * This read-only property returns the current iteration count, valid during a call to {@link doLayout}. */ get currentIteration(): number; /** * Gets or sets the space between which the layout * will position the connected graphs that together compose the network. * This defaults to Size(100, 100). * These distances are used during a clustered layout; * afterwards the normal force-directed layout * will likely cause the size of any space between connected graphs to change, * perhaps considerably. */ get arrangementSpacing(): Size; set arrangementSpacing(value: Size); /** * Gets or sets whether {@link commitNodes} should move all of the * nodes so that the nodes all fit with the top-left corner at the * {@link Layout.arrangementOrigin}. * By default this is false -- the {@link Layout.arrangementOrigin} is ignored. * When this is true, nodes are moved even though {@link isFixed} was true. */ get arrangesToOrigin(): boolean; set arrangesToOrigin(value: boolean); /** * Gets or sets whether the fromSpot and the toSpot of every {@link Link} * should be set to {@link Spot.Default}. * The default value is true. */ get setsPortSpots(): boolean; set setsPortSpots(value: boolean); /** * Gets or sets whether this layout should find all {@link Node}s * whose category is "Comment" and * whose anchors are nodes represented in the network, * and add {@link ForceDirectedVertex}es representing those balloon comments * as nodes in the network. * The default value is false. */ get comments(): boolean; set comments(value: boolean); /** * Gets or sets the maximum number of iterations to perform when doing the force-directed * spring-based prelayout. * The value must be non-negative. * The default value is 100. */ get maxPrelayoutIterations(): number; set maxPrelayoutIterations(value: number); /** * Gets or sets the maximum number of iterations to perform when doing the * force-directed auto layout. * The value must be non-negative. * The default value is 300. */ get maxIterations(): number; set maxIterations(value: number); /** * Gets or sets approximately how far a node must move in order for the iterations to continue. * The default value is 1. * The value must be larger than zero. */ get epsilonDistance(): number; set epsilonDistance(value: number); /** * Gets or sets a threshold for the distance beyond which the electrical charge forces may be ignored. * The default value is 1000. * The value must be larger than 1. */ get infinityDistance(): number; set infinityDistance(value: number); /** * Gets or sets how far a vertex may be moved in an iteration. * The default value is 10. */ get moveLimit(): number; set moveLimit(value: number); /** * Gets or sets a random number generator. * The default value is Math, which results in calling Math.random(). * Change this to null in order to use an instance of an internal repeatable pseudo-random number generator, * which will become the new value of this property. * * The new value must be either null or an Object with a method named "random" taking zero arguments * and returning a random number between zero (inclusive) and one (exclusive). */ get randomNumberGenerator(): ({ random: () => number; } | null); set randomNumberGenerator(value: ({ random: () => number; } | null)); /** * Gets or sets the default value computed by {@link springStiffness}. * The initial value is 0.05. */ get defaultSpringStiffness(): number; set defaultSpringStiffness(value: number); /** * Gets or sets the default value computed by {@link springLength}. * The initial value is 50. */ get defaultSpringLength(): number; set defaultSpringLength(value: number); /** * Gets or sets the default value computed by {@link electricalCharge}. * The initial value is 150. */ get defaultElectricalCharge(): number; set defaultElectricalCharge(value: number); /** * Gets or sets the default value computed by {@link gravitationalMass}. * The initial value is zero. */ get defaultGravitationalMass(): number; set defaultGravitationalMass(value: number); /** * Gets or sets the default value computed by {@link springLength}. * The initial value is 10. */ get defaultCommentSpringLength(): number; set defaultCommentSpringLength(value: number); /** * Gets or sets the default value computed by {@link electricalCharge}. * The initial value is 5. */ get defaultCommentElectricalCharge(): number; set defaultCommentElectricalCharge(value: number); /** * Gets or sets the quality of the prelayout operation. * The value must be greater than or equal to zero, with 0 meaning no prelayout operation * and Infinity meaning the highest quality possible prelayout. * Lower values will reduce memory usage: if the value is Infinity or greater than the size of the graph, * the algorithm will use quadratic space; if the value is 1 linear space will be used. * * The default value is NaN, which will attempt to find a good value based on the number of nodes and links * in each connected subgraph. */ get prelayoutQuality(): number; set prelayoutQuality(value: number); /** * Gets or sets the of the prelayout operation. Increasing this number will * cause the graph to be significantly more spread out, which is particularly useful in graphs with large node sizes. * Decreasing this number may reduce the number of long links in the graph. * The default value is 10. */ get prelayoutSpread(): number; set prelayoutSpread(value: number); } /** * This class represents an abstract graph of {@link ForceDirectedVertex}es and {@link ForceDirectedEdge}s * that can be constructed based on the {@link Node}s and {@link Link}s of a {@link Diagram} * so that the {@link ForceDirectedLayout} can operate independently of the diagram until it * is time to commit any node positioning or link routing. * * This class inherits from {@link LayoutNetwork}. * @category Layout * @unindexed */ export class ForceDirectedNetwork extends LayoutNetwork { constructor(layout: ForceDirectedLayout); } /** * This holds {@link ForceDirectedLayout}-specific information about {@link Node}s. * * This class inherits from {@link LayoutVertex}. * @category Layout * @unindexed */ export class ForceDirectedVertex extends LayoutVertex { constructor(network: ForceDirectedNetwork); /** * Gets or sets whether the vertex may be moved by any forces. * The default value is false. */ get isFixed(): boolean; set isFixed(value: boolean); /** * Gets or sets the electrical charge for this vertex. * The default value is NaN. */ get charge(): number; set charge(value: number); /** * Gets or sets the gravitational mass for this vertex. * The default value is NaN. */ get mass(): number; set mass(value: number); /** * Gets or sets the cumulative force on the vertex in the X direction. * The default value is zero. */ get forceX(): number; set forceX(value: number); /** * Gets or sets the cumulative force on the vertex in the Y direction. * The default value is zero. */ get forceY(): number; set forceY(value: number); } /** * This holds {@link ForceDirectedLayout}-specific information about {@link Link}s. * * This class inherits from {@link LayoutEdge}. * @category Layout * @unindexed */ export class ForceDirectedEdge extends LayoutEdge { constructor(network: ForceDirectedNetwork); /** * Gets or sets this edge's stiffness or resistance to compression or stretching. * The default value is NaN. */ get stiffness(): number; set stiffness(value: number); /** * Gets or sets the length of this edge. * The default value is NaN. */ get length(): number; set length(value: number); } /** * This enumeration specifies how {@link LayeredDigraphLayout} changes the graph to make sure it contains no cycles or loops. * Used for {@link LayeredDigraphLayout.cycleRemoveOption}. * @since 3.0 * @category Layout */ export declare enum LayeredDigraphCycleRemove { /** * Remove cycles using depth first cycle removal. */ DepthFirst = 0, /** * Remove cycles using greedy cycle removal. */ Greedy = 1, /** * Remove cycles depending on {@link LayeredDigraphLayout.assignLayers} determining entirely which links are backwards links. */ FromLayers = 2 } /** * This enumeration specifies how {@link LayeredDigraphLayout.assignLayers} assigns each node of the graph to a layer. * Used for {@link LayeredDigraphLayout.layeringOption}. * @since 3.0 * @category Layout */ export declare enum LayeredDigraphLayering { /** * Assign layers using optimal link length layering, so that links tend to cross the fewest number of layers. */ OptimalLinkLength = 10, /** * Assign layers using longest path sink layering, so that nodes are placed in the latest layer possible * possibly resulting in longer links to nodes at the last/deepest layers. */ LongestPathSink = 11, /** * Assign layers using longest path source layering, so that nodes without any predecessors are placed * in the first layer possibly resulting in longer links from nodes at the first/shallowest layers. */ LongestPathSource = 12 } /** * This enumeration specifies how {@link LayeredDigraphLayout} determines the array of indices for each layer. * Used for {@link LayeredDigraphLayout.initializeOption}. * @since 3.0 * @category Layout */ export declare enum LayeredDigraphInit { /** * Initialize using depth first out initialization. */ DepthFirstOut = 20, /** * Initialize using depth first in initialization. */ DepthFirstIn = 21, /** * Initialize using naive initialization. */ Naive = 22 } /** * This enumeration specifies how much effort {@link LayeredDigraphLayout} puts into trying to look for link crossings. * Used for {@link LayeredDigraphLayout.aggressiveOption}. * @since 3.0 * @category Layout */ export declare enum LayeredDigraphAggressive { /** * The fastest, but poorest, crossing reduction algorithm. */ None = 30, /** * The faster, less aggressive, crossing reduction algorithm. */ Less = 31, /** * The slower, more aggressive, crossing reduction algorithm. */ More = 32 } /** * These enumerated values can be bitwise combined as values for the {@link LayeredDigraphLayout.packOption} property, * which controls how much and what kinds of effort {@link LayeredDigraphLayout} makes during straightening and packing * when not using {@link LayeredDigraphLayout.alignOption}. * * We recommend using {@link LayeredDigraphLayout.alignOption} for better alignment and speed. * @since 3.0 * @deprecated * @category Layout */ export declare enum LayeredDigraphPack { /** * Does minimal work in packing the nodes. */ None = 0, /** * This option gives more chances for the packing algorithm to improve the network, * but is very expensive in time for large networks. */ Expand = 1, /** * This option tries to have the packing algorithm straighten many of the * links that cross layers. */ Straighten = 2, /** * This option tries to have the packing algorithm center groups of nodes * based on their relationships with nodes in other layers. */ Median = 4, /** * Enable all options for the {@link LayeredDigraphLayout.packOption} property. * See also {@link Expand}, {@link Straighten}, and {@link Median}. */ All = 15 } /** * These enumerated values can be bitwise combined as values for the {@link LayeredDigraphLayout.alignOption} property, * which controls how {@link LayeredDigraphLayout} attempts to align nodes during straightening and packing. * @since 3.0 * @category Layout */ export declare enum LayeredDigraphAlign { /** * This option means the the layout will pack nodes using the {@link LayeredDigraphLayout.packOption} instead of {@link LayeredDigraphLayout.alignOption}. */ None = 0, /** * This option aligns and compacts nodes based on upper neighbors, favoring leftmost neighbors. */ UpperLeft = 1, /** * This option aligns and compacts nodes based on upper neighbors, favoring rightmost neighbors. */ UpperRight = 2, /** * This option aligns and compacts nodes based on lower neighbors, favoring leftmost neighbors. */ LowerLeft = 4, /** * This option aligns and compacts nodes based on lower neighbors, favoring rightmost neighbors. */ LowerRight = 8, /** * Enable all options for the {@link LayeredDigraphLayout.alignOption} property; * See also {@link UpperLeft}, {@link UpperRight}, * {@link LowerLeft}, and {@link LowerRight}. * * This option will tend to balance nodes compared to their neighbors. */ All = 15 } /** * This arranges nodes of directed graphs into layers (rows or columns). * There are many samples that use LayeredDigraphLayout. *

* If you want to experiment interactively with most of the properties, try the Layered Digraph Layout sample. * See samples that make use of LayeredDigraphLayout in the samples index. * * The {@link layerSpacing} property controls the distance between layers. * The {@link columnSpacing} property controls the breadth of each "column" -- * this affects the distance between nodes within a layer, although the exact distance also depends on the breadth of each node. * The {@link layeringOption} property determines whether nodes without links coming in or without links going out are * lined up at the edge of the graph, or whether they are positioned close to their connected nodes. * * By default the layout will route the links in a manner that is consistent with the {@link direction}. * So, for example, if the {@link direction} is 90 degrees (i.e. downward), the links are expected to go from the top towards the bottom. * That means the links should come out from the bottom of the ports and should go into the top of the ports. * Basically the layout will set {@link Link.fromSpot} to `Spot.Bottom` and {@link Link.toSpot} to `Spot.Top`. * * If you want to the links to use the spots that are given by the ports or by the links themselves, you will need to set * {@link setsPortSpots} to false to prevent this layout from setting the spots on the links. * For example, if each node only has one port that is the whole node, and if you want the links to be spread out along the sides * of the nodes, then you should set {@link setsPortSpots} to false and set the node's {@link GraphObject.fromSpot} to * `Spot.BottomSide` and {@link GraphObject.toSpot} to `Spot.TopSide`. * * This layout handles links that form cycles better than {@link TreeLayout} does. * The normal routing behavior for "backwards" links is to route them "around" the source node and "around" the destination node, * so that all links come in one side and go out the other side. * However if you want "backwards" links to go more directly between nodes, set {@link setsPortSpots} to false and * the node's {@link GraphObject.fromSpot} and {@link GraphObject.toSpot} both to `Spot.TopBottomSides`. * (Of course if the {@link direction} is zero or 180, you'll want to use `Spot.LeftRightSides`.) * * If the diagram is structured in a tree-like fashion, * it may be better to use {@link TreeLayout}, * which has more options specific to trees. * {@link TreeLayout} is much faster than LayeredDigraphLayout, * and can handle a limited number of links that would prevent the * graph structure from being a true tree (i.e. some nodes having multiple parents). * * This layout makes use of a {@link LayoutNetwork} of * {@link LayeredDigraphVertex}es and {@link LayeredDigraphEdge}s that normally * correspond to the {@link Node}s and {@link Link}s of the {@link Diagram}. * * The layout algorithm consists of four-major steps: Cycle Removal, * Layer Assignment, Crossing Reduction, and Straightening and Packing. * The layout cannot guarantee that it provides optimal positioning of nodes or routing of links. * * The Layer Assignment step can be slow if {@link layeringOption} is * {@link LayeredDigraphLayering.OptimalLinkLength}, which is the default value. * * The CrossingReduction step is usually slow, but it can be avoided if you want to * maintain a certain order within each layer by setting {@link LayeredDigraphLayout.aggressiveOption} * to {@link LayeredDigraphAggressive.None}. * * The Straightening and Packing step is usually much slower if you set {@link alignOption} to * {@link LayeredDigraphAlign.None}, which causes the older * {@link packOption} to be used. * * If performance remains a problem, contact us. * @category Layout */ export class LayeredDigraphLayout extends Layout { /** * Constructs a {@link LayeredDigraphLayout} with no {@link Layout.network} * and with no owning {@link Layout.diagram}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Create a new {@link LayoutNetwork} of {@link LayeredDigraphVertex}es and {@link LayeredDigraphEdge}s. * @virtual * @returns a new {@link LayoutNetwork}. */ createNetwork(): LayeredDigraphNetwork; /** * Perform the layered digraph layout. * * If there is no {@link Layout.network}, this calls {@link makeNetwork} to create a {@link LayoutNetwork} from the given collection of Parts. * This removes any reflexive edges in the network, since they should be ignored. * * In order to influence a vertex's layer, you can override {@link assignLayers}. * * Finally this calls {@link Layout.updateParts} to commit the Node positions from the vertex positions. * {@link Layout.updateParts} calls {@link commitLayout} within a transaction. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ doLayout(coll: Diagram | Group | Iterable): void; /** * (undocumented) * The function LinkMinLength returns the minimum length of the * link represented by the LayeredDigraphEdge link. * The default implementation gives links a minimum length of 1. * This function can be overridden to provide "fine-tuning" of the layout. * @virtual * @param edge * @returns Returns the minimum length of the link represented by link. */ protected linkMinLength(edge: LayeredDigraphEdge): number; /** * (undocumented) * This function returns the minimum space reserved for this node from the center point * for the "depth" of the layer that it is in. * * The default implementation returns 0 for nodes that do not * correspond to top-level Go objects. For nodes that do correspond * to top-level Go objects, the layer space is determined by the * width or height of the object depending on the {@link direction}. * By default this adds 10 to the space, to account for port end segment lengths. * * @virtual * @param v * @param topleft - whether to return the distance from the vertex's position * @returns Returns the minimum space reserved above and below this node, in document coordinates. */ protected nodeMinLayerSpace(v: LayeredDigraphVertex, topleft: boolean): number; /** * (undocumented) * The function nodeMinColumnSpace returns the minimum space * reserved to either side of this node. * * The default implementation returns 0 for nodes that do not * correspond to top-level Go objects. For nodes that do correspond * to top-level Go objects, the column space is determined by the * width and height of the object divided by the {@link columnSpacing}. * Note: all sub-classes that override this method should ensure that * nodes that do not correspond to top-level Go objects have a minimum * column space of 0. * This function can be overridden to provide "fine-tuning" of the layout. * * This property has no effect on positioning of nodes when using {@link alignOption}. * @virtual * @param v * @param topleft - whether to return the distance from the vertex's position * @returns Returns the minimum space reserved to either side of the center of this node, in units of {@link columnSpacing}. */ protected nodeMinColumnSpace(v: LayeredDigraphVertex, topleft: boolean): number; /** * (undocumented) * Removes cycles from the input network by reversing some number of links. * By default, this just calls (undocumented) greedyCycleRemoval or {@link depthFirstCycleRemoval}, * as appropriate, give the value of {@link cycleRemoveOption}. * @virtual */ protected removeCycles(): void; /** * Assigns every vertex in the input network to a layer. * The layer is a non-negative integer describing which row of vertexes each vertex belongs in. * (Do not confuse this concept of "layer" with {@link Layer}s that control the Z-ordering of Parts.) * * The layering satisfies the following relationship: * if L is a link from node U to node V, then U.layer > V.layer. * * This method can be overridden to customize how nodes are assigned layers. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * By default, this does the appropriate assignments given the value of {@link layeringOption}. * @virtual */ protected assignLayers(): void; /** * (undocumented) * Assigns every node in the input network an index number, * such that nodes in the same layer will be labeled with * consecutive indices in left to right order. * All consecutive layout operations will preserve or update * the indices. * * In addition, the indices array is initialized such that * indices[layer] indicates the number of nodes in the layer. * Finally, the variables minIndexLayer and maxIndexLayer record * the layers that correspond to the minimum and maximum nodes * in a layer. * By default this will just call (undocumented) naiveInitializeIndices, * depthfirstOutInitializeIndices, or * depthfirstInInitializeIndices, as appropriate * given the value of {@link initializeOption}. * This method must not change the layer of any existing node, nor add or remove any layers. * @virtual */ protected initializeIndices(): void; /** * (undocumented) * Reorders nodes within layers to reduce the total number of link * crossings in the network. * * There are many, many possible implementations of this function. * Basically, some iteration of MedianBarycenterCrossingReduction * and AdjacentExchangeCrossingReductionBendStraighten * sweeping back and forth over the layers is needed. * The default implementation has performed favorably on a large number * of networks, but other options are available. * @virtual */ protected reduceCrossings(): void; /** * (undocumented) * Adjusts the columns of nodes in the network to produce a layout which reduces * the number of bends and is tightly packed. * * When using {@link alignOption}, nodes are assigned coordinates within their layers * to produce straighter paths of nodes and small edge lengths. * @virtual */ protected straightenAndPack(): void; /** * Set the fromSpot and toSpot on each Link, position each Node according * to the vertex position, and then position/route the Links. * * This calls the {@link commitNodes} and {@link commitLinks} methods, the latter only if {@link isRouting} is true. * You should not call this method -- it is a "protected virtual" method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. */ protected commitLayout(): void; /** * Commit the position of all nodes. * * This is called by {@link commitLayout}. * See also {@link commitLinks}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitNodes(): void; /** * This overridable method is called by {@link commitLayout} * to support custom arrangement of bands or labels across each layout layer. * By default this method does nothing. * * The coordinates used in the resulting Rects may need to be offset by the {@link Layout.arrangementOrigin}. * @virtual * @param layerRects - an Array of {@link Rect}s with the bounds of each of the "layers" * @param offset - the position of the top-left corner of the banded area relative to the coordinates given by the layerRects */ protected commitLayers(layerRects: Array, offset: Point): void; /** * Routes the links. * * This is called by {@link commitLayout}. * This is only called if {@link Layout.isRouting} is true. * See also {@link commitNodes}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitLinks(): void; /** * Gets or sets the space between each layer. * This value must be non-negative and it defaults to 25. */ get layerSpacing(): number; set layerSpacing(value: number); /** * Gets or sets the size of each column. * This value must be positive and it defaults to 25. * * When using {@link alignOption}, this will act as node spacing for nodes within a layer. */ get columnSpacing(): number; set columnSpacing(value: number); /** * Gets or sets the direction the graph grows towards. * 0 is towards the right, 90 is downwards, 180 is towards the left, and 270 is upwards. * The default value is 0. */ get direction(): number; set direction(value: number); /** * Gets or set which cycle removal option is used. * The value must be a {@link LayeredDigraphCycleRemove} value. * The default value is {@link LayeredDigraphCycleRemove.DepthFirst}. */ get cycleRemoveOption(): LayeredDigraphCycleRemove; set cycleRemoveOption(value: LayeredDigraphCycleRemove); /** * Gets or sets which layering option is being used. * The value must be a {@link LayeredDigraphLayering} value. * The default value is {@link LayeredDigraphLayering.OptimalLinkLength}, * which is also the slowest option. */ get layeringOption(): LayeredDigraphLayering; set layeringOption(value: LayeredDigraphLayering); /** * Gets or sets which indices initialization option is being used. * The value must be a {@link LayeredDigraphInit} value. * The default value is {@link LayeredDigraphInit.DepthFirstOut}. */ get initializeOption(): LayeredDigraphInit; set initializeOption(value: LayeredDigraphInit); /** * Gets or sets the number of iterations to be done. * The value must be non-negative. The default value is 4. */ get iterations(): number; set iterations(value: number); /** * Gets or sets which aggressive option is being used to look for link crossings. * The default value is {@link LayeredDigraphAggressive.Less}. * The fastest option is {@link LayeredDigraphAggressive.None}. */ get aggressiveOption(): LayeredDigraphAggressive; set aggressiveOption(value: LayeredDigraphAggressive); /** * Gets or sets the options used by the straighten and pack function; * this option is deprecated -- {@link alignOption} usually produces a better alignment, faster. * * The value must be a combination of bit flags. * The default value is {@link LayeredDigraphLayout.PackAll}, which is a combination of all three flags. * * Each of the flags has a cost; Expand is particularly slow. * However if you do not set this property, this layout will automatically turn off the Expand * option for you if the graph is large enough. * You can set this property value to {@link LayeredDigraphLayout.PackNone} to avoid most of the work. * * This option is ignored if {@link alignOption} is set to a value other than {@link LayeredDigraphAlign.None}. * This tends to be slower than {@link alignOption}, particularly for larger graphs. * Larger graphs, however, will usually be more compact than when using alignOption. * * @deprecated @see {@link alignOption} */ get packOption(): LayeredDigraphPack; set packOption(value: LayeredDigraphPack); /** * Gets or sets the options used by the straighten and pack function, as a faster * alternative to {@link packOption}. * * When using this option, nodes are assigned coordinates within their layers * to produce straighter paths of nodes and small edge lengths. * * When used as an alternative to {@link packOption}, this tends to be faster, * particularly for larger graphs. * Larger graphs, however, will usually be less compact than when using packOption. * If this option is set, packOption is ignored. * * This option does not use columns, but rather uses {@link columnSpacing} to space nodes within a layer. * * The value must be a combination of the {@link LayeredDigraphAlign} bit flags. * * Using {@link LayeredDigraphAlign.All} will tend to provide the most balanced results * and is what we recommend starting with. * * The default value is {@link LayeredDigraphAlign.All}. * When the value is {@link LayeredDigraphAlign.None}, the {@link packOption} is used instead. * * @see {@link packOption} * @since 2.3 */ get alignOption(): LayeredDigraphAlign; set alignOption(value: LayeredDigraphAlign); /** * Gets or sets whether the FromSpot and ToSpot of each link should be set * to values appropriate for the given value of {@link LayeredDigraphLayout.direction}. * The default value is true. * * If you set this to false, the spot values of the links and port objects will be used. * If you do not set the spot values to sensible values matching the {@link direction}, * the routing results may be poor and they may cross over nodes. */ get setsPortSpots(): boolean; set setsPortSpots(value: boolean); /** * This read-only property returns the largest layer value. */ get maxLayer(): number; /** * This read-only property returns the largest index value. */ get maxIndex(): number; /** * This read-only property returns the largest column value. */ get maxColumn(): number; /** * This read-only property returns the smallest index layer. */ get minIndexLayer(): number; /** * This read-only property returns the larges index layer. */ get maxIndexLayer(): number; /** * @deprecated See {@link LayeredDigraphCycleRemove.DepthFirst}. */ static readonly CycleDepthFirst = LayeredDigraphCycleRemove.DepthFirst; /** * @deprecated See {@link LayeredDigraphCycleRemove.Greedy}. */ static readonly CycleGreedy = LayeredDigraphCycleRemove.Greedy; /** * @deprecated See {@link LayeredDigraphCycleRemove.FromLayers}. */ static readonly CycleFromLayers = LayeredDigraphCycleRemove.FromLayers; /** * @deprecated See {@link LayeredDigraphLayering.OptimalLinkLength}. */ static readonly LayerOptimalLinkLength = LayeredDigraphLayering.OptimalLinkLength; /** * @deprecated See {@link LayeredDigraphLayering.LongestPathSink}. */ static readonly LayerLongestPathSink = LayeredDigraphLayering.LongestPathSink; /** * @deprecated See {@link LayeredDigraphLayering.LongestPathSource}. */ static readonly LayerLongestPathSource = LayeredDigraphLayering.LongestPathSource; /** * @deprecated See {@link LayeredDigraphInit.DepthFirstOut}. */ static readonly InitDepthFirstOut = LayeredDigraphInit.DepthFirstOut; /** * @deprecated See {@link LayeredDigraphInit.DepthFirstIn}. */ static readonly InitDepthFirstIn = LayeredDigraphInit.DepthFirstIn; /** * @deprecated See {@link LayeredDigraphInit.Naive}. */ static readonly InitNaive = LayeredDigraphInit.Naive; /** * @deprecated See {@link LayeredDigraphAggressive.None}. */ static readonly AggressiveNone = LayeredDigraphAggressive.None; /** * @deprecated See {@link LayeredDigraphAggressive.Less}. */ static readonly AggressiveLess = LayeredDigraphAggressive.Less; /** * @deprecated See {@link LayeredDigraphAggressive.More}. */ static readonly AggressiveMore = LayeredDigraphAggressive.More; /** * @deprecated */ static readonly PackNone = LayeredDigraphPack.None; /** * @deprecated */ static readonly PackExpand = LayeredDigraphPack.Expand; /** * @deprecated */ static readonly PackStraighten = LayeredDigraphPack.Straighten; /** * @deprecated */ static readonly PackMedian = LayeredDigraphPack.Median; /** * @deprecated */ static readonly PackAll = LayeredDigraphPack.All; /** * @deprecated See {@link LayeredDigraphAlign.None}. */ static readonly AlignNone = LayeredDigraphAlign.None; /** * @deprecated See {@link LayeredDigraphAlign.UpperLeft}. */ static readonly AlignUpperLeft = LayeredDigraphAlign.UpperLeft; /** * @deprecated See {@link LayeredDigraphAlign.UpperRight}. */ static readonly AlignUpperRight = LayeredDigraphAlign.UpperRight; /** * @deprecated See {@link LayeredDigraphAlign.LowerLeft}. */ static readonly AlignLowerLeft = LayeredDigraphAlign.LowerLeft; /** * @deprecated See {@link LayeredDigraphAlign.LowerRight}. */ static readonly AlignLowerRight = LayeredDigraphAlign.LowerRight; /** * @deprecated See {@link LayeredDigraphAlign.All}. */ static readonly AlignAll = LayeredDigraphAlign.All; } /** * This class represents an abstract graph of {@link LayeredDigraphVertex}es and {@link LayeredDigraphEdge}s * that can be constructed based on the {@link Node}s and {@link Link}s of a {@link Diagram} * so that the {@link LayeredDigraphLayout} can operate independently of the diagram until it * is time to commit any node positioning or link routing. * * This class inherits from {@link LayoutNetwork}. * @category Layout * @unindexed */ export class LayeredDigraphNetwork extends LayoutNetwork { constructor(layout: LayeredDigraphLayout); } /** * This holds {@link LayeredDigraphLayout}-specific information about {@link Node}s. * * This class inherits from {@link LayoutVertex}. * @category Layout * @unindexed */ export class LayeredDigraphVertex extends LayoutVertex { constructor(network: LayeredDigraphNetwork); /** * @param edge */ addSourceEdge(edge: LayoutEdge): void; /** * @param edge */ deleteSourceEdge(edge: LayoutEdge): void; /** * @param edge */ addDestinationEdge(edge: LayoutEdge): void; /** * @param edge */ deleteDestinationEdge(edge: LayoutEdge): void; /** * Gets or sets the layer to which the node is assigned. * The default value is -1. */ get layer(): number; set layer(value: number); /** * Gets or sets the column to which the node is assigned. * The default value is -1. * * This property is not used during straightening and packing of nodes * when using {@link LayeredDigraphLayout.alignOption}. */ get column(): number; set column(value: number); /** * Gets or sets the index to which the node is assigned. * The default value is -1. */ get index(): number; set index(value: number); /** * Gets or sets the connected component to which the node is assigned. * The default value is NaN. * * This property is not used during straightening and packing of nodes * when using {@link LayeredDigraphLayout.alignOption}. */ get component(): number; set component(value: number); /** * Gets or sets another LayeredDigraphVertex in the same layer that this node should be near. * The default value is null. */ get near(): LayeredDigraphVertex; set near(value: LayeredDigraphVertex); } /** * This holds {@link LayeredDigraphLayout}-specific information about {@link Link}s. * * This class inherits from {@link LayoutEdge}. * @category Layout * @unindexed */ export class LayeredDigraphEdge extends LayoutEdge { constructor(network: LayeredDigraphNetwork); /** * Gets or sets the {@link LayoutVertex} that this edge comes from. * Setting this property does not change any {@link LayoutVertex.destinationEdges} collection. */ get fromVertex(): LayeredDigraphVertex | null; set fromVertex(value: LayeredDigraphVertex | null); /** * Gets or sets the {@link LayoutVertex} that this edge goes to. * Setting this property does not change any {@link LayoutVertex.sourceEdges} collection. */ get toVertex(): LayeredDigraphVertex | null; set toVertex(value: LayeredDigraphVertex | null); /** * True if the link is part of the proper digraph. * The default value is false. */ get valid(): boolean; set valid(value: boolean); /** * True if the link was reversed during cycle removal. * The default value is false. */ get rev(): boolean; set rev(value: boolean); /** * True if the link is part of the depth first forest. * The default value is false. */ get forest(): boolean; set forest(value: boolean); /** * Location of the port at the from node of the link. * Allows the crossing matrix to correctly calculate the crossings for nodes with multiple ports. * The default value is NaN. * * This property is also used to align link ports when using {@link LayeredDigraphLayout.alignOption}. */ get portFromPos(): number; set portFromPos(value: number); /** * Location of the port at the to node of the link. * Allows the crossing matrix to correctly calculate the crossings for nodes with multiple ports. * The default value is NaN. * * This property is also used to align link ports when using {@link LayeredDigraphLayout.alignOption}. */ get portToPos(): number; set portToPos(value: number); /** * Approximate column offset of the from port of the link from the from node column used in straightening. * The default value is 0. */ get portFromColOffset(): number; set portFromColOffset(value: number); /** * Approximate column offset of the to port of the link from the to node column used in straightening. * The default value is 0. */ get portToColOffset(): number; set portToColOffset(value: number); } /** * This enumeration specifies how to build a tree from the {@link TreeNetwork}. * Used for {@link TreeLayout.path}. * @since 3.0 * @category Layout */ export declare enum TreePath { /** * Causes the value of {@link Diagram.isTreePathToChildren} to effectively choose either {@link Destination} (if true) * or {@link Source} (if false). */ Default = 0, /** * The children of a {@link TreeVertex} are its {@link LayoutVertex.destinationVertexes}, * the collection of connected {@link LayoutEdge.toVertex}es. * * The tree roots are those {@link TreeVertex}es that have zero source edges. */ Destination = 1, /** * The children of a {@link TreeVertex} are its {@link LayoutVertex.sourceVertexes}, * the collection of connected {@link LayoutEdge.fromVertex}es. * * The tree roots are those {@link TreeVertex}es that have zero destination edges. */ Source = 2 } /** * This enumeration specifies whether to sort the children of a node, and in what order to position them. * Used for {@link TreeLayout.sorting} or {@link TreeLayout.alternateSorting}. * @since 3.0 * @category Layout */ export declare enum TreeSorting { /** * Lay out each child in the order in which they were found. */ Forwards = 10, /** * Lay out each child in reverse order from which they were found. */ Reverse = 11, /** * Lay out each child according to the sort order given by {@link TreeVertex.comparer}. */ Ascending = 12, /** * Lay out each child in reverse sort order given by {@link TreeVertex.comparer}. */ Descending = 13 } /** * This enumeration specifies how to position a parent {@link TreeVertex} relative to its children, * or how to align children in a bus. * Used for {@link TreeLayout.alignment} or {@link TreeLayout.alternateAlignment}. * @since 3.0 * @category Layout */ export declare enum TreeAlignment { /** * The parent is centered at the middle of the range of its child subtrees. * * When there is a breadth limit that causes there to be multiple rows, * the links that extend from the parent to those children in rows past * the first one may cross over the nodes that are in earlier rows. */ CenterSubtrees = 20, /** * The parent is centered at the middle of the range of its immediate child nodes. * * When there is a breadth limit that causes there to be multiple rows, * the links that extend from the parent to those children in rows past * the first one may cross over the nodes that are in earlier rows. */ CenterChildren = 21, /** * The parent is positioned near the first of its children. */ Start = 22, /** * The parent is positioned near the last of its children. */ End = 23, /** * The children are positioned in a bus on both sides of an "aisle" where the links to them go, * with the last odd child (if any) placed at the end of the aisle in the middle. * * The children, if they are themselves parents, continue at the same inherited angle; * use {@link BusBranching} if you want grandchildren to proceed growing in * the different angle as determined by the side. * * A bus does not take {@link TreeVertex.breadthLimit} into account. */ Bus = 24, /** * Like {@link Bus} with the children arranged on both sides of an "aisle" * with any last odd child placed at the end of the aisle, * but the children get an {@link TreeVertex.angle} that depends on which side of the aisle * they were placed. * * This only works well when the {@link TreeLayout.treeStyle} is {@link TreeStyle.Layered}. * * A bus does not take {@link TreeVertex.breadthLimit} into account. */ BusBranching = 25, /** * The children are positioned in a bus, only on the top or left side of the parent. * * A bus does not take {@link TreeVertex.breadthLimit} into account. */ TopLeftBus = 26, /** * The children are positioned in a bus, only on the bottom or right side of the parent. * * A bus does not take {@link TreeVertex.breadthLimit} into account. */ BottomRightBus = 27, /** * (undocumented) */ Custom = 28 } /** * This enumeration specifies how closely packed the children of a node should be. * Used for {@link TreeLayout.compaction} or {@link TreeLayout.alternateCompaction}. * @since 3.0 * @category Layout */ export declare enum TreeCompaction { /** * Only simple placement of children next to each other, as determined by their subtree breadth. * * For any node, there will not be another node at any depth occupying the same breadth position, * unless there are multiple rows; In other words, if there is no breadth limit resulting in * multiple rows, with this compaction mode it is as if every node were infinitely deep. */ None = 30, /** * A simple fitting of subtrees. * * This mode produces more compact trees -- often nicer looking too; * Nodes will not overlap each other, unless you have negative values * for some of the spacing properties; * However it is possible when the links are orthogonally styled that * occasionally the subtrees will be placed so close together that some * links may overlap the links or even the nodes of other subtrees. */ Block = 31 } /** * This enumeration specifies the general style in which the nodes are laid out. * Used for {@link TreeLayout.treeStyle}. * @since 3.0 * @category Layout */ export declare enum TreeStyle { /** * The normal tree style, where all of the children of each {@link TreeVertex} are lined up * horizontally or vertically. * * Each {@link TreeVertex} gets its properties from its parent node; * {@link TreeLayout.rootDefaults} is used for all default {@link TreeVertex} property values; * {@link TreeLayout.alternateDefaults} is ignored. */ Layered = 40, /** * Just like the standard layered tree style, except that the nodes with children but no grandchildren * have alternate properties. * * Each {@link TreeVertex} gets its properties from its parent node; * However, for those nodes whose {@link TreeVertex.maxGenerationCount} is 1, * in other words when it has children but no grandchildren, * the properties are copied from {@link TreeLayout.alternateDefaults}. * * If the tree only has two levels, the root node gets the {@link TreeLayout.rootDefaults}. */ LastParents = 41, /** * Alternate layers of the tree have different properties, typically including the angle. * * Each {@link TreeVertex} gets its properties from its grandparent node; * The root nodes get their defaults from {@link TreeLayout.rootDefaults}. * * The immediate children of root nodes get their defaults from {@link TreeLayout.alternateDefaults}. * * Depending on the properties used, it is possible for some link routes to cross over nodes. */ Alternating = 42, /** * All of the nodes get the alternate properties, except the root node gets the default properties. * * The root node gets the {@link TreeLayout.rootDefaults} properties, * the root node's children get the {@link TreeLayout.alternateDefaults} properties, * and all the rest of the {@link TreeVertex}es get their properties from their parent node. */ RootOnly = 43 } /** * This enumeration specifies how to position the resulting trees in the document. * Used for {@link TreeLayout.arrangement}. * @since 3.0 * @category Layout */ export declare enum TreeArrangement { /** * Position each tree in a non-overlapping fashion by increasing Y coordinates, * starting at the {@link Layout.arrangementOrigin}. */ Vertical = 50, /** * Position each tree in a non-overlapping fashion by increasing X coordinates, * starting at the {@link Layout.arrangementOrigin}. */ Horizontal = 51, /** * Do not move each root node, but position all of their descendants relative to their root. */ FixedRoots = 52 } /** * This enumeration specifies the manner in which nodes are placed into layers. * Used for {@link TreeLayout.layerStyle}. * @since 3.0 * @category Layout */ export declare enum TreeLayerStyle { /** * The normal layer style, where each node takes up only the depth that it needs. */ Individual = 60, /** * A layer style where all of the children of a parent node take up the same amount of depth -- * this typically causes all cousins to be aligned. */ Siblings = 61, /** * A layer style where all nodes with the same {@link TreeVertex.level} throughout the tree take up the same amount of depth -- * if the {@link TreeVertex.angle} is the same for all nodes, this will result in all nodes in the same layer to be aligned. */ Uniform = 62 } /** * This layout positions nodes of a tree-structured graph in layers (rows or columns). *

* For a discussion and examples of the most commonly used properties, see Trees page in the Introduction. * If you want to experiment interactively with most of the properties, try the Tree Layout sample. * See samples that make use of TreeLayout in the samples index. * * This layout makes use of a {@link LayoutNetwork} of * {@link TreeVertex}es and {@link TreeEdge}s that normally * correspond to the {@link Node}s and {@link Link}s of the {@link Diagram}. * * The most commonly set properties for controlling the results of a TreeLayout are: * - {@link angle}: the direction in which the tree grows, from parent to child; * the default value of zero means that the tree grows towards the right, with the children of a node arranged in a layer that is a column. * An angle of 0 or 180 means that children form vertical layers -- breadth is height and depth is width; * an angle of 90 or 270 means that children form horizontal layers -- breadth is width and depth is height. * - {@link layerSpacing}: the distance between layers -- between a parent node and its child nodes. * - {@link nodeSpacing}: the distance between nodes within a layer -- between siblings. * - {@link alignment}: the relative position of a parent node with its children. * - {@link sorting} and {@link comparer}: specify the order of the immediate children of a parent node. * - {@link compaction}: whether subtrees should be packed closer together if there is room. * - {@link layerStyle}: whether the children of one node are aligned with the children of a sibling node. * - {@link setsPortSpot}, {@link portSpot}, {@link setsChildPortSpot}, and {@link childPortSpot}: this controls whether to set the {@link Link.fromSpot} and * {@link Link.toSpot} to be sensible for the {@link angle}. * - {@link nodeIndent} and {@link nodeIndentPastParent}: if the {@link alignment} is {@link TreeAlignment.Start} or {@link TreeAlignment.End}, * control how much extra space the first child is given when positioned. * - {@link breadthLimit}, {@link rowSpacing}: try to limit the total breadth of a subtree to a certain distance; * when there are too many children or when they are too broad, this puts children into additional rows (or columns, depending on the angle) * thereby limiting the breadth while increasing the depth of the tree. * * When you set one of the TreeLayout properties listed above, that property normally applies to all of the nodes in the tree. * What if you want {@link alignment} to be {@link TreeAlignment.CenterChildren} for the root node but {@link TreeAlignment.Bus} for the other nodes in the tree? * Or what if you want want {@link layerSpacing} to be 50 for all layers except for the layer separating "leaf" nodes from their parent? * * One common solution is to set {@link treeStyle}. * For the former scenario, you could set {@link treeStyle} to {@link TreeStyle.RootOnly}; the value of {@link alignment} would only apply to the root node. * For the latter scenario, you could set it to {@link TreeStyle.LastParents}; * the value of {@link layerSpacing} would apply to all nodes except those that have children but that do not have grandchildren. * How do you then set the alignment or layerSpacing for the other nodes? * By setting the TreeLayout properties whose names start with "alternate...". * In these cases that would mean setting {@link alternateAlignment} or {@link alternateLayerSpacing}. * * These TreeLayout properties actually apply to the {@link TreeVertex} that the TreeLayout uses to represent a {@link Node} within the {@link LayoutNetwork}. * All of those TreeLayout properties are actually stored in {@link rootDefaults}; all of the "alternate..." properties are stored in {@link alternateDefaults}. * Depending on the value of {@link treeStyle}, the actual TreeVertex properties for each Node are copied appropriately from either rootDefaults or alternateDefaults. * In the default case where treeStyle is {@link TreeStyle.Layered}, the alternateDefaults are ignored. * (Note that treeStyle, and a few other properties such as {@link path} and {@link arrangement}, apply to the whole layout, not to an individual node/vertex.) * * The use of {@link treeStyle} and "alternate..." TreeLayout properties will cover a lot of common needs for tree layout customization. * However, there may be times when that is not enough. * Imagine a situation where you want a special {@link TreeVertex} property value for a particular {@link Node}. * The solution is to override {@link assignTreeVertexValues}, where you can examine the given {@link TreeVertex}, * including its corresponding {@link LayoutVertex.node}, to decide what TreeVertex property values should apply. * @category Layout */ export class TreeLayout extends Layout { /** * Constructs a {@link TreeLayout} with no {@link Layout.network} * and with no owning {@link Layout.diagram}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Create a new {@link LayoutNetwork} of {@link TreeVertex}es and {@link TreeEdge}s. * @returns a new {@link LayoutNetwork}. */ createNetwork(): TreeNetwork; /** * Create and initialize a {@link LayoutNetwork} with the given nodes and links. * * This does not include any nodes of category "Comment". * Comment nodes are added by the {@link addComments} method. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ makeNetwork(coll: Diagram | Group | Iterable): LayoutNetwork; /** * Perform the tree layout. * * If there is no {@link Layout.network}, this calls {@link makeNetwork} to create a {@link LayoutNetwork} from the given collection of Parts. * * If there are no {@link TreeVertex} {@link roots} specified, this finds all roots in the {@link Layout.network}. * * This initializes all of the {@link TreeVertex}es and {@link TreeEdge}s, calling {@link initializeTreeVertexValues} on each vertex, * supporting inheritance of vertex values. * Then it calls {@link assignTreeVertexValues} on each one, to allow for node/vertex-specific customizations. * Next it sorts all of the child vertexes for each parent vertex, if needed. * * This also calls {@link addComments} of each vertex, in order to find any comment nodes associated with each vertex, * so that they can be accommodated by the layout. * * This then actually does the "layout" of the vertexes and optionally the routing of the edges of each tree in the network. * To deal with multiple roots/trees this also calls {@link arrangeTrees} to position each separate tree relative to each other. * * Finally this calls {@link Layout.updateParts} to commit the Node positions from the vertex positions and the Link routes from the edges. * {@link Layout.updateParts} calls {@link commitLayout} within a transaction. * @param coll - A {@link Diagram} or a {@link Group} or a collection of {@link Part}s. */ doLayout(coll: Diagram | Group | Iterable): void; /** * Assign initial property values for a {@link TreeVertex}. * * The values may be inherited, so this method is called while * propagating values from the root nodes. * This method should not walk the tree, since it is called for each * {@link TreeVertex} in a depth-first manner starting at a root. * * You probably do not need to override this method, * but if you do you should call first either the base method * or {@link TreeVertex.copyInheritedPropertiesFrom}, since they * assign most of the {@link TreeVertex} property values * used to influence the layout. * Informational properties such as {@link TreeVertex.descendantCount} * and {@link TreeVertex.maxGenerationCount} will not yet have been initialized * by the time this method is called. * It is more common to override {@link assignTreeVertexValues} in order to * modify a property or two to customize the layout at that node. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * When the {@link TreeVertex.alignment} is {@link TreeAlignment.BusBranching}, * this will modify the {@link TreeVertex.angle} appropriately depending on which * side of the bus the vertex is on. * @virtual * @param v */ initializeTreeVertexValues(v: TreeVertex): void; /** * Assign final property values for a {@link TreeVertex}. * * This method is commonly overridden in order to provide * tree layout properties for particular nodes. * This method is called after values have been inherited from other * {@link TreeVertex}es, so you can examine and modify the * values of related tree nodes. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * * However, when {@link TreeVertex.alignment} is {@link TreeAlignment.BusBranching}, * changing the {@link TreeVertex.sorting} or * {@link TreeVertex.comparer} properties in this method will have no effect. * * This method should not walk the tree, since it is called for each * {@link TreeVertex} in a depth-first manner starting at a root. * * Here is an example where the children are squeezed together if there are many of them, * but only on nodes that have no grandchildren. This makes use of two {@link TreeVertex} * properties that are automatically computed for you, {@link TreeVertex.childrenCount} and {@link TreeVertex.descendantCount}. * ```js * class SqueezingTreeLayout extends go.TreeLayout { * assignTreeVertexValues(v) { * if (v.childrenCount > 6 && v.childrenCount === v.descendantCount) { * v.alignment = go.TreeAlignment.BottomRightBus; * v.layerSpacing = 10; * v.rowSpacing = 0; * } * } * } * ``` * * If you need to assign TreeVertex values and also have them be "inherited" by the child vertexes, * you should override {@link initializeTreeVertexValues} instead. * However at the time that method is called, the computed properties of TreeVertex will not be available. * @virtual * @param v */ assignTreeVertexValues(v: TreeVertex): void; /** * Find any associated objects to be positioned along with the {@link LayoutVertex.node}. * * This looks for visible {@link Node}'s whose category is "Comment" and * that refer to the tree vertex's {@link Node}. * This method is only called when {@link comments} is true. * * You may want to override this method in order to customize how * any associated objects are found and how the node's {@link LayoutVertex.bounds} * are set to reserve space for those associated objects. * This method should not walk the tree, since it is called for each * {@link TreeVertex} in an indeterminate order. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param v */ addComments(v: TreeVertex): void; /** * Position and {@link TreeVertex.comments} around the vertex. * * This method should not walk the tree, since it is called for each * {@link TreeVertex} in an indeterminate order. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param v */ layoutComments(v: TreeVertex): void; /** * (Undocumented) * @virtual * @param v * @param offx * @param offy * @param subw * @param subh */ customAlignment(v: TreeVertex, offx: number, offy: number, subw: number, subh: number): Array; /** * Get the amount of space to insert between a child vertex and its parent spine * when the parent's {@link TreeVertex.alignment} is Bus or BusBranching. * * This function is called on each child vertex to determine the initial distance of a child * from the spine that connects to its parent vertex. * This function is not called on the last odd child * because that vertex is placed at the end of the spine rather than to either side. * @virtual * @param child * @returns By default this returns the parent's {@link TreeVertex.nodeSpacing}; * a small value may result in unpleasant routing of links, * a negative value may cause the node overlaps. */ computeBusNodeSpacing(child: TreeVertex): number; /** * Get the amound of space to leave between the sibling child vertexes and this last odd vertex * when the parent's {@link TreeVertex.alignment} is Bus or BusBranching. * * This function is called only when there is an odd number of child vertexes. * This function is not called when the parent vertex only has one child. * In that case there is no spine separating the two columns of child vertexes. * @virtual * @param lastchild * @param dist - the length of the central line (spine) separating the two sides, * so far excluding the initial {@link TreeVertex.nodeSpacing} * that extends form the parent's spine. * @returns By default this returns the parent's {@link TreeVertex.rowSpacing}; * a negative value may cause node overlaps. */ computeBusLastRowSpacing(lastchild: TreeVertex, dist: number): number; /** * Position each separate tree. * * This is called after each tree has been laid out and thus each subtree * bounds are known. * The {@link arrangement} and {@link arrangementSpacing} and {@link Layout.arrangementOrigin} * properties affect this method's behavior. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ arrangeTrees(): void; /** * Set the fromSpot and toSpot on each Link, position each Node according * to the vertex position, and then position/route the Links. * * This calls the {@link commitNodes} and {@link commitLinks} methods, the latter only if {@link isRouting} is true. * You should not call this method -- it is a "protected virtual" method. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. */ protected commitLayout(): void; /** * Commit the position of all nodes. * * This is called by {@link commitLayout}. * See also {@link commitLinks}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitNodes(): void; /** * This overridable method is called by {@link commitLayout} * if {@link layerStyle} is LayerUniform * to support custom arrangement of bands or labels across each layout layer. * By default this method does nothing. * * The coordinates used in the resulting Rects may need to be offset by the {@link Layout.arrangementOrigin} * and/or by the arrangement of subtrees done by {@link arrangeTrees}. * @virtual * @param layerRects - an Array of {@link Rect}s with the bounds of each of the "layers" * @param offset - the position of the top-left corner of the banded area relative to the coordinates given by the layerRects */ protected commitLayers(layerRects: Array, offset: Point): void; /** * Routes the links. * * This is called by {@link commitLayout}. * This is only called if {@link Layout.isRouting} is true. * See also {@link commitNodes}. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual */ protected commitLinks(): void; /** * @virtual * @param v */ computeLayerSpacing(v: TreeVertex): number; /** * @virtual * @param v */ computeNodeIndent(v: TreeVertex): number; /** * Gets or sets the collection of root vertexes. * * Initially this will be an empty {@link Set | go.Set}. * * If the {@link path} is either {@link TreePath.Destination|Destination} or * {@link TreePath.Source|Source}, this layout can easily * determine all of the tree roots by searching the whole network. * Otherwise, you should explicitly initialize this collection * with one or more {@link TreeVertex}es. */ get roots(): Set<(TreeVertex | Node)>; set roots(value: Set<(TreeVertex | Node)>); /** * Gets or sets how the tree should be constructed from the * {@link TreeEdge}s connecting {@link TreeVertex}es. * Must be a {@link TreePath} value. * * The default value is {@link TreePath.Default}, * where the value of {@link Diagram.isTreePathToChildren} determines the effective value of this property. */ get path(): TreePath; set path(value: TreePath); /** * Gets or sets the Style for the resulting trees. * Must be a {@link TreeStyle} value. * * The default value is {@link TreeStyle.Layered}. */ get treeStyle(): TreeStyle; set treeStyle(value: TreeStyle); /** * Gets or sets the manner in which the nodes are aligned in layers. * Must be a {@link TreeLayerStyle} value. * * The default value is {@link TreeLayerStyle.Individual}. */ get layerStyle(): TreeLayerStyle; set layerStyle(value: TreeLayerStyle); /** * Gets or sets whether this layout should find all {@link Node}s * whose category is "Comment" and * whose anchors are nodes represented in the network, * and increase the size of the corresponding TreeVertex to make room for the comment nodes. * The default value is true. */ get comments(): boolean; set comments(value: boolean); /** * Gets or sets how {@link arrangeTrees} should lay out the separate trees. * Must be a {@link TreeArrangement} value. * * The default value is {@link TreeArrangement.Vertical} */ get arrangement(): TreeArrangement; set arrangement(value: TreeArrangement); /** * Gets or sets the space between which {@link arrangeTrees} will position the trees. * * This defaults to the Size(10, 10). * * This property is ignored if {@link arrangement} is {@link TreeArrangement.FixedRoots}. */ get arrangementSpacing(): Size; set arrangementSpacing(value: Size); /** * Gets or sets the object holding the default values for root {@link TreeVertex}es. * * The values for the following inheritable properties are actually stored in this object: * {@link sorting}, {@link comparer}, {@link angle}, * {@link alignment}, {@link nodeIndent}, {@link nodeIndentPastParent}, * {@link nodeSpacing}, {@link layerSpacing}, {@link layerSpacingParentOverlap}, * {@link compaction}, {@link breadthLimit}, {@link rowSpacing}, {@link rowIndent}, * {@link commentSpacing}, {@link commentMargin}, * {@link setsPortSpot}, {@link portSpot}, {@link setsChildPortSpot}, {@link childPortSpot}. * The other properties of this {@link TreeVertex} are ignored. */ get rootDefaults(): TreeVertex; set rootDefaults(value: TreeVertex); /** * Gets or sets the object holding the default values for alternate layer {@link TreeVertex}es, * used when the {@link treeStyle} is {@link TreeStyle.Alternating|Alternating} or {@link TreeStyle.LastParents|LastParents}. * * See the list of inheritable properties in the documentation for {@link rootDefaults}. * The other properties of this {@link TreeVertex} are ignored. */ get alternateDefaults(): TreeVertex; set alternateDefaults(value: TreeVertex); /** * Gets or sets the default sorting policy for ordering the immediate children of a vertex. * Must be a {@link TreeSorting} value. * * The default value is {@link TreeSorting.Forwards}. * * This sets the {@link rootDefaults}' property of the same name. * The sort order is determined by {@link comparer}. */ get sorting(): TreeSorting; set sorting(value: TreeSorting); /** * Gets or sets the default comparison function used for sorting the immediate children of a vertex. * * The default comparer compares the {@link LayoutVertex.node} Text values. * * This sets the {@link rootDefaults}' property of the same name. * Whether this comparison function is used is determined by the value of {@link sorting}. * ```js * new go.TreeLayout({ * sorting: go.TreeSorting.Ascending, * comparer: (va, vb) => { * const da = va.node.data; * const db = vb.node.data; * if (da.someProperty < db.someProperty) return -1; * if (da.someProperty > db.someProperty) return 1; * return 0; * } * }) * ``` */ get comparer(): ((a: TreeVertex, b: TreeVertex) => number); set comparer(value: ((a: TreeVertex, b: TreeVertex) => number)); /** * Gets or sets the default direction for tree growth. * * The default value is 0; the value must be one of: 0, 90, 180, 270. * * These values are in degrees, where 0 is along the positive X axis, * and where 90 is along the positive Y axis. * * This sets the {@link rootDefaults}' property of the same name. */ get angle(): number; set angle(value: number); /** * Gets or sets the default alignment of parents relative to their children. * Must be a {@link TreeAlignment} value. * * The default value is {@link TreeAlignment.CenterChildren}. * * This sets the {@link rootDefaults}' property of the same name. */ get alignment(): TreeAlignment; set alignment(value: TreeAlignment); /** * Gets or sets the default indentation of the first child. * * The default value is zero. The value should be non-negative. * * This property is only sensible when the {@link alignment} * is {@link TreeAlignment.Start|Start} or {@link TreeAlignment.End|End}. * Having a positive value is useful if you want to reserve space * at the start of the row of children for some reason. * For example, if you want to pretend the parent node is infinitely deep, * you can set this to be the breadth of the parent node. * * This sets the {@link rootDefaults}' property of the same name. */ get nodeIndent(): number; set nodeIndent(value: number); /** * Gets or sets the fraction of this node's breadth is added to {@link nodeIndent} * to determine any spacing at the start of the children. * * The default value is 0.0 -- the only indentation is specified by {@link nodeIndent}. * When the value is 1.0, the children will be indented past the breadth of the parent node. * * This property is only sensible when the {@link alignment} * is {@link TreeAlignment.Start|Start} or {@link TreeAlignment.End|End}. * * This sets the {@link rootDefaults}' property of the same name. */ get nodeIndentPastParent(): number; set nodeIndentPastParent(value: number); /** * Gets or sets the distance between child nodes. * * This is the distance between sibling nodes. * A negative value causes sibling nodes to overlap. * The default value is 20. * * The {@link layerSpacing} property determines the distance between a parent node and the layer of its children. * * This sets the {@link rootDefaults}' property of the same name. */ get nodeSpacing(): number; set nodeSpacing(value: number); /** * Gets or sets the distance between a parent node and its children. * * This is the distance between a parent node and the layer of its children. * Negative values may cause children to overlap with the parent. * The default value is 50. * * The {@link nodeSpacing} property determines the distance between siblings. * The {@link rowSpacing} property determines the distance * between multiple rows or columns of children. * * This sets the {@link rootDefaults}' property of the same name. */ get layerSpacing(): number; set layerSpacing(value: number); /** * Gets or sets the fraction of the node's depth for which the children's layer starts overlapped with the parent's layer. * * The default value is 0.0 -- there is overlap between layers only if {@link layerSpacing} is negative. * A value of 1.0 and a zero {@link layerSpacing} will cause child nodes to completely overlap the parent. * * A value greater than zero may still cause overlap between layers, * unless the value of {@link layerSpacing} is large enough. * A value of zero might still allow overlap between layers, * if {@link layerSpacing} is negative. * * This sets the {@link rootDefaults}' property of the same name. */ get layerSpacingParentOverlap(): number; set layerSpacingParentOverlap(value: number); /** * Gets or sets how closely to pack the child nodes of a subtree. * Must be a {@link TreeCompaction} value. * * The default value is {@link TreeCompaction.Block|Block}. * * This sets the {@link rootDefaults}' property of the same name. */ get compaction(): TreeCompaction; set compaction(value: TreeCompaction); /** * Gets or sets a limit on how broad a tree should be. * * A value of zero (the default) means there is no limit; * a positive value specifies a limit. * The default value is zero. * * This property is just a suggested constraint on how * broadly the tree will be laid out. * When there isn't enough breadth for all of the children of a node, * the children are placed in as many rows as needed to try to stay * within the given breadth limit. * If the value is too small, since this layout algorithm * does not modify the size or shape of any node, the nodes will * just be laid out in a line, one per row, and the breadth is * determined by the broadest node. * The distance between rows is specified by {@link rowSpacing}. * To make room for the links that go around earlier rows to get to * later rows, when the alignment is not a "center" alignment, the * {@link rowIndent} property specifies that space at the * start of each row. * * This sets the {@link rootDefaults}' property of the same name. */ get breadthLimit(): number; set breadthLimit(value: number); /** * Gets or sets the distance between multiple rows or columns of a parent node's immediate children * when the breadth occupied by the children is limited by {@link breadthLimit}. * * The default value is 25. * * This property is only used when there is more than one * row of children for a given parent node. * The {@link nodeSpacing} property determines the distance between siblings. * The {@link layerSpacing} property determines the distance between * the parent node and its first row or column of child nodes. * The {@link rowIndent} property determines any indentation for all of the rows. * * This sets the {@link rootDefaults}' property of the same name. */ get rowSpacing(): number; set rowSpacing(value: number); /** * Gets or sets the default indentation of the first child of each row, * if the {@link alignment} is not a "Center" alignment, * when the breadth occupied by the children is limited by {@link breadthLimit}. * * The default value is 10. The value should be non-negative. * * This is used to leave room for the links that connect a parent node * with the child nodes that are in additional rows. * The {@link rowSpacing} property determines the distance between the rows or columns when there is more than one. * * This sets the {@link rootDefaults}' property of the same name. */ get rowIndent(): number; set rowIndent(value: number); /** * Gets or sets the distance between comments. * * The default value is 10. * * This is used by {@link addComments} and {@link layoutComments}. * * This sets the {@link rootDefaults}' property of the same name. */ get commentSpacing(): number; set commentSpacing(value: number); /** * Gets or sets the distance between a node and its comments. * * The default value is 20. * * This is used by {@link addComments} and {@link layoutComments}. * * This sets the {@link rootDefaults}' property of the same name. */ get commentMargin(): number; set commentMargin(value: number); /** * Gets or sets whether the TreeLayout should set the * FromSpot for this parent node port. * * The default value is true -- this may modify the spot of the port of this node, the parent, * if the node has only a single port. * * The spot used depends on the value of {@link portSpot}. * * This sets the {@link rootDefaults}' property of the same name. */ get setsPortSpot(): boolean; set setsPortSpot(value: boolean); /** * Gets or sets the spot that this node's port gets as its FromSpot. * * The default value is {@link Spot.Default}. * * A value of {@link Spot.Default} will cause the TreeLayout * to assign a FromSpot based on the parent node's {@link TreeVertex.angle}. * If the value is other than NoSpot, it is just assigned. * When {@link path} is {@link TreePath.Source|Source}, * the port's ToSpot is set instead of the FromSpot. * * This sets the {@link rootDefaults}' property of the same name. */ get portSpot(): Spot; set portSpot(value: Spot); /** * Gets or sets whether the TreeLayout should set the * ToSpot for each child node port. * * The default value is true -- this may modify the spot of the ports of the children nodes, * if the node has only a single port. * * The spot used depends on the value of {@link childPortSpot}. * * This sets the {@link rootDefaults}' property of the same name. */ get setsChildPortSpot(): boolean; set setsChildPortSpot(value: boolean); /** * Gets or sets the spot that children nodes' ports get as their ToSpot. * * The default value is {@link Spot.Default}. * * A value of {@link Spot.Default} will cause the TreeLayout * to assign a ToSpot based on the parent node's {@link TreeVertex.angle}. * If the value is other than NoSpot, it is just assigned. * When {@link path} is {@link TreePath.Source|Source}, * the port's FromSpot is set instead of the ToSpot. * * This sets the {@link rootDefaults}' property of the same name. */ get childPortSpot(): Spot; set childPortSpot(value: Spot); /** * Gets or sets the alternate sorting policy for ordering the immediate children of a vertex. * Must be a {@link TreeSorting} value. * * The default value is {@link TreeSorting.Forwards|Forwards}. * * This sets the {@link alternateDefaults}' property of the same name. * The sort order is determined by {@link alternateComparer}. */ get alternateSorting(): TreeSorting; set alternateSorting(value: TreeSorting); /** * Gets or sets the alternate comparison function used for sorting the immediate children of a vertex. * * The default comparer compares the {@link LayoutVertex.node} Text values. * * This sets the {@link alternateDefaults}' property of the same name. * Whether this comparison function is used is determined by the value of {@link alternateSorting}. */ get alternateComparer(): ((a: TreeVertex, b: TreeVertex) => number); set alternateComparer(value: ((a: TreeVertex, b: TreeVertex) => number)); /** * Gets or sets the alternate direction for tree growth. * * The default value is 0; the value must be one of: 0, 90, 180, 270. * * These values are in degrees, where 0 is along the positive X axis, * and where 90 is along the positive Y axis. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateAngle(): number; set alternateAngle(value: number); /** * Gets or sets the alternate alignment of parents relative to their children. * Must be a {@link TreeAlignment} value. * * The default value is {@link TreeAlignment.CenterChildren}. * * This sets the {@link alternateDefaults}' property of the same name. */ get alternateAlignment(): TreeAlignment; set alternateAlignment(value: TreeAlignment); /** * Gets or sets the alternate indentation of the first child. * * The default value is zero. The value should be non-negative. * * This property is only sensible when the {@link alignment} * is {@link TreeAlignment.Start|Start} or {@link TreeAlignment.End|End}. * Having a positive value is useful if you want to reserve space * at the start of the row of children for some reason. * For example, if you want to pretend the parent node is infinitely deep, * you can set this to be the breadth of the parent node. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateNodeIndent(): number; set alternateNodeIndent(value: number); /** * Gets or sets the fraction of this node's breadth is added to {@link alternateNodeIndent} * to determine any spacing at the start of the children. * * The default value is 0.0 -- the only indentation is specified by {@link alternateNodeIndent}. * When the value is 1.0, the children will be indented past the breadth of the parent node. * * This property is only sensible when the {@link alignment} * is {@link TreeAlignment.Start|Start} or {@link TreeAlignment.End|End}. */ get alternateNodeIndentPastParent(): number; set alternateNodeIndentPastParent(value: number); /** * Gets or sets the alternate distance between child nodes. * * The default value is 20. * * A negative value causes sibling nodes to overlap. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateNodeSpacing(): number; set alternateNodeSpacing(value: number); /** * Gets or sets the alternate distance between a parent node and its children. * * The default value is 50. * * This is the distance between a parent node and its first row * of children, in case there are multiple rows of its children. * The {@link alternateNodeSpacing} property determines the distance between siblings. * The {@link alternateRowSpacing} property determines the distance * between rows of children. * Negative values may cause children to overlap with the parent. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateLayerSpacing(): number; set alternateLayerSpacing(value: number); /** * Gets or sets the alternate fraction of the node's depth for which the children's layer starts overlapped with the parent's layer. * * The default value is 0.0 -- there is overlap between layers only if {@link alternateLayerSpacing} is negative. * A value of 1.0 and a zero {@link alternateLayerSpacing} will cause child nodes to completely overlap the parent. * * A value greater than zero may still cause overlap between layers, * unless the value of {@link alternateLayerSpacing} is large enough. * A value of zero might still allow overlap between layers, * if {@link alternateLayerSpacing} is negative. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateLayerSpacingParentOverlap(): number; set alternateLayerSpacingParentOverlap(value: number); /** * Gets or sets how closely to pack the child nodes of a subtree. * Must be a {@link TreeCompaction} value. * * The default value is {@link TreeCompaction.Block}. * * This sets the {@link alternateDefaults}' property of the same name. */ get alternateCompaction(): TreeCompaction; set alternateCompaction(value: TreeCompaction); /** * Gets or sets an alternate limit on how broad a tree should be. * * A value of zero (the default) means there is no limit; * a positive value specifies a limit. * The default value is zero. * * This property is just a suggested constraint on how * broadly the tree will be laid out. * When there isn't enough breadth for all of the children of a node, * the children are placed in as many rows as needed to try to stay * within the given breadth limit. * If the value is too small, since this layout algorithm * does not modify the size or shape of any node, the nodes will * just be laid out in a line, one per row, and the breadth is * determined by the broadest node. * The distance between rows is specified by {@link alternateRowSpacing}. * To make room for the links that go around earlier rows to get to * later rows, when the alignment is not a "center" alignment, the * {@link alternateRowIndent} property specifies that space at the * start of each row. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateBreadthLimit(): number; set alternateBreadthLimit(value: number); /** * Gets or sets the alternate distance between rows of children. * * The default value is 25. * * This property is only used when there is more than one * row of children for a given parent node. * The {@link alternateLayerSpacing} property determines the distance between * the parent node and its first row of child nodes. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateRowSpacing(): number; set alternateRowSpacing(value: number); /** * Gets or sets the alternate indentation of the first child of each row, * if the {@link alignment} is not a "Center" alignment. * * The default value is 10. The value should be non-negative. * * This is used to leave room for the links that connect a parent node * with the child nodes that are in additional rows. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateRowIndent(): number; set alternateRowIndent(value: number); /** * Gets or sets the alternate distance between comments. * * The default value is 10. * * This is used by {@link addComments} and {@link layoutComments}. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateCommentSpacing(): number; set alternateCommentSpacing(value: number); /** * Gets or sets the alternate distance between a node and its comments. * * The default value is 20. * * This is used by {@link addComments} and {@link layoutComments}. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateCommentMargin(): number; set alternateCommentMargin(value: number); /** * Gets or sets whether the TreeLayout should set the * FromSpot for this parent node port. * * The default value is true -- this may modify the spot of the port of this node, the parent, * if the node has only a single port. * * The spot used depends on the value of {@link alternatePortSpot}. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateSetsPortSpot(): boolean; set alternateSetsPortSpot(value: boolean); /** * Gets or sets the alternate spot that this node's port gets as its FromSpot. * * The default value is {@link Spot.Default}. * * A value of {@link Spot.Default} will cause the TreeLayout * to assign a FromSpot based on the parent node's {@link TreeVertex.angle}. * If the value is other than NoSpot, it is just assigned. * When {@link path} is {@link TreePath.Source|Source}, * the port's ToSpot is set instead of the FromSpot. * This sets the {@link alternateDefaults}' property of the same name. */ get alternatePortSpot(): Spot; set alternatePortSpot(value: Spot); /** * Gets or sets whether the TreeLayout should set the * ToSpot for each child node port. * * The default value is true -- this may modify the spot of the ports of the children nodes, * if the node has only a single port. * * The spot used depends on the value of {@link alternateChildPortSpot}. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateSetsChildPortSpot(): boolean; set alternateSetsChildPortSpot(value: boolean); /** * Gets or sets the alternate spot that children nodes' ports get as their ToSpot * The default value is {@link Spot.Default}. * * A value of {@link Spot.Default} will cause the TreeLayout * to assign a ToSpot based on the parent node's {@link TreeVertex.angle}. * * If the value is other than NoSpot, it is just assigned. * When {@link path} is {@link TreePath.Source|Source}, * the port's FromSpot is set instead of the ToSpot. * This sets the {@link alternateDefaults}' property of the same name. */ get alternateChildPortSpot(): Spot; set alternateChildPortSpot(value: Spot); /** * @deprecated See {@link TreePath.Default}. */ static readonly PathDefault = TreePath.Default; /** * @deprecated See {@link TreePath.Destination}. */ static readonly PathDestination = TreePath.Destination; /** * @deprecated See {@link TreePath.Source}. */ static readonly PathSource = TreePath.Source; /** * @deprecated See {@link TreeSorting.Forwards}. */ static readonly SortingForwards = TreeSorting.Forwards; /** * @deprecated See {@link TreeSorting.Reverse}. */ static readonly SortingReverse = TreeSorting.Reverse; /** * @deprecated See {@link TreeSorting.Ascending}. */ static readonly SortingAscending = TreeSorting.Ascending; /** * @deprecated See {@link TreeSorting.Descending}. */ static readonly SortingDescending = TreeSorting.Descending; /** * @deprecated See {@link TreeAlignment.CenterSubtrees}. */ static readonly AlignmentCenterSubtrees = TreeAlignment.CenterSubtrees; /** * @deprecated See {@link TreeAlignment.CenterChildren}. */ static readonly AlignmentCenterChildren = TreeAlignment.CenterChildren; /** * @deprecated See {@link TreeAlignment.Start}. */ static readonly AlignmentStart = TreeAlignment.Start; /** * @deprecated See {@link TreeAlignment.End}. */ static readonly AlignmentEnd = TreeAlignment.End; /** * @deprecated See {@link TreeAlignment.Bus}. */ static readonly AlignmentBus = TreeAlignment.Bus; /** * @deprecated See {@link TreeAlignment.BusBranching}. */ static readonly AlignmentBusBranching = TreeAlignment.BusBranching; /** * @deprecated See {@link TreeAlignment.TopLeftBus}. */ static readonly AlignmentTopLeftBus = TreeAlignment.TopLeftBus; /** * @deprecated See {@link TreeAlignment.BottomRightBus}. */ static readonly AlignmentBottomRightBus = TreeAlignment.BottomRightBus; /** * @deprecated See {@link TreeCompaction.None}. */ static readonly CompactionNone = TreeCompaction.None; /** * @deprecated See {@link TreeCompaction.Block}. */ static readonly CompactionBlock = TreeCompaction.Block; /** * @deprecated See {@link TreeStyle.Layered}. */ static readonly StyleLayered = TreeStyle.Layered; /** * @deprecated See {@link TreeStyle.LastParents}. */ static readonly StyleLastParents = TreeStyle.LastParents; /** * @deprecated See {@link TreeStyle.Alternating}. */ static readonly StyleAlternating = TreeStyle.Alternating; /** * @deprecated See {@link TreeStyle.RootOnly}. */ static readonly StyleRootOnly = TreeStyle.RootOnly; /** * @deprecated See {@link TreeArrangement.Vertical}. */ static readonly ArrangementVertical = TreeArrangement.Vertical; /** * @deprecated See {@link TreeArrangement.Horizontal}. */ static readonly ArrangementHorizontal = TreeArrangement.Horizontal; /** * @deprecated See {@link TreeArrangement.FixedRoots}. */ static readonly ArrangementFixedRoots = TreeArrangement.FixedRoots; /** * @deprecated See {@link TreeLayerStyle.Individual}. */ static readonly LayerIndividual = TreeLayerStyle.Individual; /** * @deprecated See {@link TreeLayerStyle.Siblings}. */ static readonly LayerSiblings = TreeLayerStyle.Siblings; /** * @deprecated See {@link TreeLayerStyle.Uniform}. */ static readonly LayerUniform = TreeLayerStyle.Uniform; } /** * This class represents an abstract graph of {@link TreeVertex}es and {@link TreeEdge}s * that can be constructed based on the {@link Node}s and {@link Link}s of a {@link Diagram} * so that the {@link TreeLayout} can operate independently of the diagram until it * is time to commit any node positioning or link routing. * * This class inherits from {@link LayoutNetwork}. * @category Layout * @unindexed */ export class TreeNetwork extends LayoutNetwork { constructor(layout: TreeLayout); } /** * This holds {@link TreeLayout}-specific information about {@link Node}s. * * This class inherits from {@link LayoutVertex}. * @category Layout * @unindexed */ export class TreeVertex extends LayoutVertex { constructor(network: TreeNetwork); /** * Copy inherited properties from another TreeVertex to this one. * @virtual * @param copy */ copyInheritedPropertiesFrom(copy: TreeVertex): void; /** * Gets or sets whether this node has been initialized as part of {@link TreeLayout.doLayout} when building the tree structures. * * The default value is false. */ get initialized(): boolean; set initialized(value: boolean); /** * Gets or sets the logical parent for this node. * * The default value is null. * * This structural property is computed in {@link TreeLayout.doLayout} when building the tree structures. * You should probably not be setting this property. */ get parent(): TreeVertex; set parent(value: TreeVertex); /** * Gets or sets the logical children for this node. * * The default value is an empty array. * * This structural property is computed in {@link TreeLayout.doLayout} when building the tree structures. * You should probably not be setting this property. */ get children(): Array; set children(value: Array); /** * Gets or sets the number of single-parent ancestors this node has. * * This could also be interpreted as which layer this node is in. * A root node will have a value of zero. * * This informational property is computed in {@link TreeLayout.doLayout} when building the tree structures. * You should probably not be setting this property. */ get level(): number; set level(value: number); /** * Gets or sets the number of descendants this node has. * * For a leaf node, this will be zero. * * This informational property is computed as part of the {@link TreeLayout.initializeTreeVertexValues} pass. * You should probably not be setting this property. */ get descendantCount(): number; set descendantCount(value: number); /** * Gets or sets the maximum number of children of any descendant of this node. * * For a leaf node, this will be zero. * * This informational property is computed as part of the {@link TreeLayout.initializeTreeVertexValues} pass. * You should probably not be setting this property. */ get maxChildrenCount(): number; set maxChildrenCount(value: number); /** * Gets or sets the maximum depth of the subtrees below this node. * * For a leaf node, this will be zero. * * This informational property is computed as part of the {@link TreeLayout.initializeTreeVertexValues} pass. * You should probably not be setting this value. */ get maxGenerationCount(): number; set maxGenerationCount(value: number); /** * Gets or sets an array of {@link Node}s that will be positioned near this node. * * The default value is null. * * These objects should not have their own {@link TreeVertex}es to be laid out. * Typically these will be {@link Node}s whose Category is "Comment". * This array should be allocated and initialized in {@link TreeLayout.addComments}. */ get comments(): Array; set comments(value: Array); /** * Gets or sets whether and in what order the children should be sorted. * * The default value is {@link TreeSorting.Forwards}. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get sorting(): TreeSorting; set sorting(value: TreeSorting); /** * Gets or sets how the children should be sorted. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get comparer(): ((a: TreeVertex, b: TreeVertex) => number); set comparer(value: ((a: TreeVertex, b: TreeVertex) => number)); /** * Gets or sets the absolute angle at which this subtree should grow from this vertex. * * The default value is zero, meaning that general tree growth should proceed rightwards along the X axis. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * By default this is the same as the Angle of the parent {@link TreeVertex}. * However, after the initial propagation of property values, perhaps in * an override of {@link TreeLayout.assignTreeVertexValues}, * you could just set this property to specify the angle at which this node grows its subtrees. */ get angle(): number; set angle(value: number); /** * Gets or sets how this parent node should be aligned relative to its children. * * The default value is {@link TreeAlignment.CenterChildren}. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get alignment(): TreeAlignment; set alignment(value: TreeAlignment); /** * Gets or sets the distance the first child should be indented. * * The default value is zero. The value should be non-negative. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * This property is only sensible when the {@link alignment} is * {@link TreeAlignment.Start} or {@link TreeAlignment.End}. */ get nodeIndent(): number; set nodeIndent(value: number); /** * Gets or sets whether the first child should be indented past the parent node's breadth. * * The default value is 0.0 -- the only start or end spacing is provided by {@link nodeIndent}. * Values must range from 0.0 to 1.0, where 1.0 means the full breadth of this node. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * This property is only sensible when the {@link alignment} is * {@link TreeAlignment.Start} or {@link TreeAlignment.End}. */ get nodeIndentPastParent(): number; set nodeIndentPastParent(value: number); /** * Gets or sets the distance between child nodes. * * The default value is 20. * * A negative value will cause sibling nodes to overlap. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get nodeSpacing(): number; set nodeSpacing(value: number); /** * Gets or sets the distance between this node and its children. * * The default value is 50. * * Negative values may cause children to overlap with the parent. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get layerSpacing(): number; set layerSpacing(value: number); /** * Gets or sets the fraction of this node's depth that may overlap with the children's layer. * * The default value is 0.0 -- there is overlap only if {@link layerSpacing} is negative. * Values must range from 0.0 to 1.0, where 1.0 means the full depth of this node. * * When this value is greater than 0.0, there might not be overlap if {@link layerSpacing} * is larger than the depth of this node times this fraction. * Even when this value is 0.0, there may be overlap when {@link layerSpacing} is negative. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get layerSpacingParentOverlap(): number; set layerSpacingParentOverlap(value: number); /** * Gets or sets how the children of this node should be packed together. * * The default value is {@link TreeCompaction.Block}. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get compaction(): TreeCompaction; set compaction(value: TreeCompaction); /** * Gets or sets how broad a node and its descendants should be. * * By default this is zero. A value of zero imposes no limit; * a positive value will specify a limit for the total width of this subtree. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get breadthLimit(): number; set breadthLimit(value: number); /** * Gets or sets the distance between rows within one layer, all sharing the same parent. * * The default value is 25. * * Negative values may cause nodes to overlap. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get rowSpacing(): number; set rowSpacing(value: number); /** * Gets or sets the distance the first child of each row should be indented. * * The default value is 10. The value should be non-negative. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * This property is only used when the {@link breadthLimit} is positive, * and some initial space needs to be reserved in each row of nodes for the links * that are routed around those rows. */ get rowIndent(): number; set rowIndent(value: number); /** * Gets or sets the space to leave between consecutive comments. * * The default value is 10. * * Negative values may cause comments to overlap. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get commentSpacing(): number; set commentSpacing(value: number); /** * Gets or sets the space to leave between the node and the comments. * * The default value is 20. * * Negative values may cause comments to overlap with the node. * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. */ get commentMargin(): number; set commentMargin(value: number); /** * Gets or sets whether the TreeLayout should set the FromSpot for this parent node port. * * The default value is true -- this may modify the spot of the port of this node, the parent, * if the node has only a single port. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * The spot used depends on the value of {@link portSpot}. */ get setsPortSpot(): boolean; set setsPortSpot(value: boolean); /** * Gets or sets the spot that this node's port gets as its FromSpot, * if {@link setsPortSpot} is true and the node has only a single port. * * The default value is {@link Spot.Default}. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * A value of {@link Spot.Default} will cause the TreeLayout * to assign a FromSpot based on the parent node's {@link TreeVertex.angle}. * If the value is other than NoSpot, it is just assigned. * When {@link TreeLayout.path} is {@link TreePath.Source}, the port's ToSpot is set instead of the FromSpot. */ get portSpot(): Spot; set portSpot(value: Spot); /** * Gets or sets whether the TreeLayout should set the ToSpot for each child node port. * * The default value is true -- this may modify the spots of the ports of the children nodes, * if the node has only a single port. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * The spot used depends on the value of {@link childPortSpot}. */ get setsChildPortSpot(): boolean; set setsChildPortSpot(value: boolean); /** * Gets or sets the spot that children nodes' ports get as their ToSpot, * if {@link setsChildPortSpot} is true and the node has only a single port. * * The default value is {@link Spot.Default}. * * This inherited property is initialized in the {@link TreeLayout.initializeTreeVertexValues} pass. * A value of {@link Spot.Default} will cause the TreeLayout * to assign a ToSpot based on the parent node's {@link TreeVertex.angle}. * If the value is other than NoSpot, it is just assigned. * When {@link TreeLayout.path} is {@link TreePath.Source}, the port's FromSpot is set instead of the ToSpot. */ get childPortSpot(): Spot; set childPortSpot(value: Spot); /** * This read-only property returns the number of immediate children this node has. * * The default value is zero. */ get childrenCount(): number; /** * Gets or sets the position of this node relative to its parent node. * * This informational property is computed during {@link TreeLayout.doLayout}. * You should probably not be setting this property. */ get relativePosition(): Point; set relativePosition(value: Point); /** * Gets or sets the size of the subtree (including all descendants) parented by this node. * * This informational property is computed during {@link TreeLayout.doLayout}. * Of course if there are no children, this is just the same as Size. * You should probably not be setting this property. */ get subtreeSize(): Size; set subtreeSize(value: Size); /** * Gets or sets the offset of this parent node relative to its whole subtree. * * This informational property is computed during {@link TreeLayout.doLayout}. * Of course if there are no children, this is just (0, 0). * You should probably not be setting this property. */ get subtreeOffset(): Point; set subtreeOffset(value: Point); } /** * This holds {@link TreeLayout}-specific information about {@link Link}s. * * This class inherits from {@link LayoutEdge}. * @category Layout * @unindexed */ export class TreeEdge extends LayoutEdge { constructor(network: TreeNetwork); /** * Commits the position of the Link and routes it. */ commit(): void; /** * Gets or sets the {@link LayoutVertex} that this edge comes from. * Setting this property does not change any {@link LayoutVertex.destinationEdges} collection. */ get fromVertex(): TreeVertex; set fromVertex(value: TreeVertex); /** * Gets or sets the {@link LayoutVertex} that this edge goes to. * Setting this property does not change any {@link LayoutVertex.sourceEdges} collection. */ get toVertex(): TreeVertex | null; set toVertex(value: TreeVertex | null); /** * Gets or sets a Point, relative to the parent node, * that may be useful in routing this link. */ get relativePoint(): Point; set relativePoint(value: Point); } /** * This static class specifies the built in themes. * * {@link Light} and {@link Dark} are the default light and dark themes * initialized by the {@link ThemeManager}. Note that these themes are complete, * so if you update values in the light theme, you'll also need to update the dark theme since * the values exist in both and won't use a default fallback. * @since 3.0 */ export class Themes { /** * The default light theme used by {@link ThemeManager}. * The name of this theme is "light". * * Defined as the following: * ```ts * { * colors: { * text: '#0a0a0a', // Neutral 950 * comment: '#ca8a04', // Yellow 600 * link: '#0a0a0a', // Neutral 950 * group: '#a3a3a344', // Neutral 400, partially transparent * outline: '#a3a3a3', // Neutral 400 * selection: '#0ea5e9', // Sky 500 * div: '#fff', * gridMinor: '#e5e5e5', // Neutral 200 * gridMajor: '#a3a3a3', // Neutral 400 * overviewBox: '#c026d3', // Fuschia 600 * tempLink: '#2563eb', // Blue 600 * tempPort: '#c026d3', // Fuschia 600 * adornmentFill: '#0ea5e9', // Sky 500 * adornmentStroke: '#1e40af', // Blue 800 * dragSelect: '#c026d3' // Fuschia 600 * }, * fonts: { * normal: '10pt sans-serif', * bold: 'bold 12pt sans-serif' * }, * numbers: { * group: 1, // group strokeWidth * selection: 3 // selection strokeWidth * }, * margins: { * group: new Margin(5) // group padding * }, * arrowheads: { * toArrow: 'Standard' * } * } * ``` */ static readonly Light: Theme; /** * The default dark theme used by {@link ThemeManager}. * The name of this theme is "dark". * * Defined as the following: * ```ts * { * colors: { * text: '#f5f5f5', // Neutral 100 * comment: '#facc15', // Yellow 400 * link: '#f5f5f5', // Neutral 100 * group: '#a3a3a388', // Neutral 400, partially transparent * outline: '#a3a3a3', // Neutral 400 * selection: '#38bdf8', // Sky 400 * div: '#171717', // Neutral 900 * gridMinor: '#262626', // Neutral 800 * gridMajor: '#404040', // Neutral 700 * overviewBox: '#e879f9', // Fuschia 400 * tempLink: '#60a5fa', // Blue 400 * tempPort: '#e879f9', // Fuschia 400 * adornmentFill: '#38bdf8', // Sky 400 * adornmentStroke: '#2563eb', // Blue 600 * dragSelect: '#e879f9' // Fuschia 400 * }, * fonts: { * normal: '10pt sans-serif', * bold: 'bold 12pt sans-serif' * }, * numbers: { * group: 1, // group strokeWidth * selection: 3 // selection strokeWidth * }, * margins: { * group: new Margin(5) // group padding * }, * arrowheads: { * toArrow: 'Standard' * } * } * ``` */ static readonly Dark: Theme; } /** * This class is responsible for managing a Diagram's theming (or multiple Diagrams, if shared). * * Read more about theming at Theming. * * Your templates can make use of the values held by the current {@link Theme} by calling * {@link GraphObject.theme} or {@link GraphObject.themeData} or {@link GraphObject.themeModel} methods, * or by adding a {@link ThemeBinding} to a GraphObject when using {@link GraphObject.make}. * All theme bindings are OneWay only -- from source data to target GraphObject property. * * Use {@link GraphObject.theme} to look up a value directly from the current Theme. * Use {@link GraphObject.themeData} to look up a value in the current Theme based on the value * of a data property. * Use {@link GraphObject.themeModel} to look up a value in the current Theme based on the value * of a data property on the {@link Model.modelData} shared object. * * For example: * ```js * myDiagram.nodeTemplate = * new go.Node('Auto').add( * new go.Shape('RoundedRectangle', { strokeWidth: 2 }) * .theme('fill', 'primary') // Shape.fill is set to the current theme's colors.primary * .theme('stroke', 'border'), // Shape.stroke is set to the current theme's colors.border * new go.TextBlock({ margin: 8 }) * .bind('text', 'key') * .theme('stroke', 'text') // stroke color is a dark or light gray * ); * ``` * * See {@link Themes} for the definitions of the two predefined Themes that are normally used. * * There are additional theming resources defined in * Themes.js * in the extensions or extensionsJSM directories. * @since 3.0 */ export class ThemeManager { /** * Constructs a ThemeManager. * * If a {@link themeMap} isn't provided, this gets default `light` and `dark` themes * that are copies of {@link Themes.Light} and {@link Themes.Dark}, respectively. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Gets or sets the map of theme names -> Themes for this ThemeManager. */ get themeMap(): Map; set themeMap(value: Map); /** * Gets or sets the default theme for this ThemeManager. * * This property determines which theme is used as a fallback if a lookup * doesn't find a value in the current theme. * @defaultValue `light` */ get defaultTheme(): string; set defaultTheme(value: string); /** * Gets or sets the current theme for this ThemeManager. * * A value of `system` will rely on the browser's preferred color scheme, * using `light` or `dark` themes. * @defaultValue `light` */ get currentTheme(): string; set currentTheme(value: string); /** * Gets or sets whether this ThemeManager changes the div background color when {@link currentTheme} changes. * * If true, the background color will be set to the CSS color string denoted by the `div` property * of the {@link Theme.colors} object. * @defaultValue `false` */ get changesDivBackground(): boolean; set changesDivBackground(value: boolean); /** * This read-only property returns the user's preferred color scheme, * useful when {@link currentTheme} is set to `system`. * * See https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme. */ get preferredColorScheme(): 'light' | 'dark'; /** * Make sure this ThemeManager knows about a {@link Diagram} for which it should handle theming. * @param diagram - A {@link Diagram} that this ThemeManager is theming. * @return this * @see {@link removeDiagram} */ addDiagram(diagram: Diagram): this; /** * Inform this ThemeManager that it will no longer handle theming for a given diagram. * @param diagram - A {@link Diagram} that this ThemeManager should no longer theme. * @return this * @see {@link addDiagram} */ removeDiagram(diagram: Diagram): this; /** * Set a particular theme and update all associated theme bindings. * Note that this will modify the named Theme object via a merge if it exists. * * If passed `system`, this method will create/update the {@link preferredColorScheme} theme. * @param themeName - which theme to change, or the empty string to update the default theme * @param props - a partial Theme object to merge into the given theme or add as a new theme * @return this */ set(themeName: string, props: Partial): this; /** * Finds a value in this ThemeManager's themes. * * By default, this first looks in the {@link currentTheme}, then the {@link defaultTheme}. * Because {@link findTheme} is called, this method also handles {@link currentTheme} being `system`. * * The default implementation is: * ```js * return this.getValue(this.findTheme(this.currentTheme), prop, source, tprop) || this.getValue(this.findTheme(this.defaultTheme), prop, source, tprop); * ``` * * This method may be overridden to search Themes in different orders. * Please read the Introduction page on Extensions for how to override methods and how to call this base method. * @virtual * @param prop - a property to search for in the Theme, * also accepting '.'-separated paths, an array of strings representing a path, or an index to an array element * @param source - where to perform the lookup within the Theme object * @param tprop - an optional target property name, used if a full path is not provided, * which can determine the property on the Theme object to search via {@link Theme.targetPropertyMap} * @returns the value found, or undefined if not found */ findValue(prop: string | Array | number, source?: string | Array, tprop?: string): any; /** * Gets a value from the given Theme. * @virtual * @param theme - the Theme to search * @param prop - a property to search for in the Theme, * also accepting '.'-separated paths, an array of strings representing a path, or an index to an array element * @param source - where to perform the lookup within the Theme object * @param tprop - an optional target property name, used if a full path is not provided, * which can determine the property on the Theme object to search via {@link Theme.targetPropertyMap} * @returns the value in the given Theme, or undefined if not found */ getValue(theme: Theme, prop: string | Array | number, source?: string | Array, tprop?: string): any; /** * Finds the {@link Theme} with the specified name, or if the name is `system`, the preferred `light` or `dark` theme. * @param themeName - the theme name to get from {@link themeMap} * @returns a Theme, or undefined if the Theme was not found */ findTheme(themeName: string): Theme | undefined; } /** * An interface describing a theme. * * The various optional properties this interface provides are the default * object names used to lookup some binding target properties. For example, * {@link Panel.padding} is looked up in the {@link margins} object and * {@link Shape.strokeWidth} and {@link GraphObject.opacity} are looked up in the {@link numbers} object. * * While the indexer can be used for other arbitrary objects, we suggest using the optional named properties * here for their respective purposes. * @since 3.0 */ export interface Theme { /** * The colors used by the theme. * See {@link ThemeColors}. */ colors?: ThemeColors; /** * The fonts used by the theme. * * Built-in themes provide values for `normal` and `bold` fonts. */ fonts?: ThemeValues; /** * The numbers used by the theme, most commonly specifying stroke widths. * * Built-in themes provide values for `group` and `selection` stroke widths. */ numbers?: ThemeValues; /** The {@link Point}s used by the theme. */ points?: ThemeValues; /** The {@link Size}s used by the theme. */ sizes?: ThemeValues; /** The {@link Rect}s used by the theme. */ rects?: ThemeValues; /** * The {@link Margin}s used by the theme. * * Built-in themes provide a `group` value for the default Group template's {@link Placeholder.padding}. */ margins?: ThemeValues; /** The {@link Spot}s used by the theme. */ spots?: ThemeValues; /** * The arrowheads used for Link shapes. * Values should correspond with valid arrowhead names for {@link Shape.fromArrow} and {@link Shape.toArrow}. * * Built-in themes provide a `toArrow` value for the default link template. */ arrowheads?: ThemeValues; /** The string index, allowing for any other {@link ThemeValues} object */ [index: string]: ThemeValues | undefined; /** * A map of GraphObject target properties to Theme objects. * This determines where a lookup will occur for a given property. * For example, one might map {@link Shape.fill} to the {@link colors} object via "fill" -> "colors". * * If not defined, or a target property is missing, some sensible defaults are provided. */ targetPropertyMap?: Map; } /** * An interface describing an object with string or number keys and values of a given type. * @since 3.0 */ export interface ThemeValues { [index: string]: T; } /** * An interface describing an object with string or number keys and BrushLike values. * * The optional properties on this interface outline various values used by default templates. * * Setting these values allows for some customization of built in templates without providing new * definitions. For example, one could use the default link template and customize the color: * ```js * myDiagram.themeManager.set('', { * colors: { link: 'turquoise' } * }); * ``` * * Or change the color of the selection adornment without providing custom `selectionAdornmentTemplate`s: * ```js * myDiagram.themeManager.set('', { * colors: { selection: 'pink' } * }); * ``` * @since 3.0 */ export interface ThemeColors { /** * The text color of the built in node, group, and item template. */ text?: BrushLike; /** * The stroke color of the built in "Comment" node template and link template. */ comment?: BrushLike; /** * The stroke/fill color the built in link template and link label. */ link?: BrushLike; /** * The fill color of the built in group shape. */ group?: BrushLike; /** * The stroke color of the built in group shape. */ outline?: BrushLike; /** * The stroke color of the default selection adornment. */ selection?: BrushLike; /** * The background color of the diagram's div, if using {@link ThemeManager.changesDivBackground}. */ div?: string; /** * The stroke color of minor gridlines in the default {@link Diagram.grid}. */ gridMinor?: BrushLike; /** * The stroke color of major gridlines in the default {@link Diagram.grid}. */ gridMajor?: BrushLike; /** * The stroke color of the default {@link Overview.box}. */ overviewBox?: BrushLike; /** * The stroke color of the default {@link LinkingBaseTool.temporaryLink}. */ tempLink?: BrushLike; /** * The stroke color of the default {@link LinkingBaseTool.temporaryFromPort} and {@link LinkingBaseTool.temporaryToPort}. */ tempPort?: BrushLike; /** * The fill color of the various default tool handles, such as {@link ResizingTool.handle}. */ adornmentFill?: BrushLike; /** * The stroke color of the various default tool handles, such as {@link ResizingTool.handle}. */ adornmentStroke?: BrushLike; /** * The stroke color of the default {@link DragSelectingTool.box}. */ dragSelect?: BrushLike; /** * The index property, allowing for any other color or group of colors to be defined. */ [index: string]: BrushLike | Array | ThemeColors | undefined; } /** * A Router is a class that is responsible for the paths of a collection of Links. * * Some routers modify the {@link Link.points} of some Links in ways that the default * routing provided by {@link Link.computePoints} cannot, because the latter method * only considers the properties of the Link and its connected ports -- not other Nodes or Links. * * Some routers modify other aspects of Links. * * The most commonly used Router is the * AvoidsLinksRouter extension * in the extensions or extensionsJSM directories. * * The Router class is abstract and does not really provide any functionality of its own. * You can install a Router subclass by constructing and initializing it and then inserting * it into the {@link Diagram.routers} list. * ```js * myDiagram.routers.add(new AvoidsLinksRouter()); * ``` * * A Router that has been installed will automatically operate on the Links of Groups or * the top-level Links of the Diagram. * * You can disable a Router by setting its {@link isEnabled} property to false, * or by overriding {@link canRoute} to decide when it should operate. * * Your subclass of Router should override {@link routeLinks} method in order * to examine the Links implicitly given to the method. * @since 3.0 * @category Layout */ export abstract class Router { /** * Don't construct this directly -- this is an abstract class. */ constructor(); /** * Gets or sets the name of this router. */ get name(): string; set name(value: string); /** * Gets or sets whether this router is enabled. */ get isEnabled(): boolean; set isEnabled(value: boolean); /** * Gets or sets whether this router runs during real-time operations, such as dragging or resizing. * The default is true. */ get isRealtime(): boolean; set isRealtime(value: boolean); /** * Gets or sets the Diagram this router is associated with. * Routers cannot be shared. */ get diagram(): Diagram; set diagram(value: Diagram); /** * If this router has been added to a diagram, calling this method will ensure the Diagram re-runs all routing. * * The router should call this method when setting properties that might require the router to re-run when values change. */ invalidateRouter(): void; /** * Determine for the given collection if this router can route. * * Adding a Router to the Diagram will cause the Diagram to call `canRoute` for every group recursively, * and finally for the Diagram itself. * * By default this returns `false` if {@link isRealtime} is `false` and a realtime operation (such as dragging or resizing) is ongoing, * or else `false` if a default animation is running, or else the value of {@link isEnabled}. * * If `true`, {@link routeLinks} will be called on each collection. * * An override of this method should return `false` if {@link isEnabled} is false, or return `false` is if a call to the base method is `false`. * * This method is only called by the {@link Diagram}. If using a Router without adding it to a Diagram, this method will never be called. * @param container A Diagram or Group on which the Router will operate. * @virtual */ canRoute(container: Diagram | Group): boolean; /** * Route the links for a given collection (Group or Diagram). By default this is called * in a depth-first manner on every Group in the Diagram, and then the Diagram itself. * If a layout occurred for a Group or a Diagram, this is called immediately afterwards * if {@link canRoute} returns true. * * It is common to route all links in each Group's {@link Group.memberParts}, * and then all top-level links in the {@link Diagram.links} collection. * (All Links that have {@link Part.containingGroup} `=== null`) * * The first argument is a Set of Links that the Diagram has collected which it considers invalid. * Typically, these are the only links that need routing. Since `routeLinks` is called with each Group * and then the Diagram, you should check the {@link Part.containingGroup} on each Link to ensure it matches: * * ```ts * public routeLinks(links: Set, container: Diagram | Group): void { * const grp = container instanceof Diagram ? null : container; * const it = links.iterator; * while (it.next()) { * const link = it.value; * // Only operate on links that are in the corresponding collection, if one is given * if (link.containingGroup !== grp) continue; * . . . * ``` * * However you may wish to design your router so that {@link canRoute} is false for Groups, * in which case you will want to operate on each of the Links in the first argument, * regardless of whether or not it is a top-level Link. * * This method should not check the {@link canRoute} predicate. * * @param links The set of links that were recently recomputed, which may need routing. * @param container A Diagram or Group on which the Router will operate. * When calling a router manually, this does not need to be specified. * @virtual */ routeLinks(links: Set, container: Diagram | Group): void; } /** * The AvoidsNodesRouter is a Router that will modify any Orthogonal {@link Link}s * for which {@link Link.isAvoiding} is true, for example if such links have {@link Routing.AvoidsNodes}. * By default, every initialized Diagram will contain a single Router, which is an AvoidsNodesRouter. * * The router will operate on all links for which {@link Link.isAvoiding} is true, unless the link is a self-loop, * a temporary link, or the Nodes connected by the link themselves overlap. * * The router will attempt to minimize or eliminate any overlaps between each Link and nearby Nodes, adding or modifying segments as * necessary, while minimizing the resulting length of the link. * * The {@link AvoidsNodesRouter} will not, in general, respect the {@link Link.fromEndSegmentLength} and {@link Link.toEndSegmentLength} * properties of a {@link Link}. */ export class AvoidsNodesRouter extends Router { /** * Constructs a {@link AvoidsNodesRouter}. * @param init - Optional initialization properties. */ constructor(init?: Partial); /** * Determine whether the AvoidsNodesRouter should operate on a given collection. * If no avoiding links are present in the collection, the router will not run. */ canRoute(container: Diagram | Group): boolean; /** * Route the links. * By default this is called in a depth-first manner on every Group in the Diagram, and then the Diagram itself. * If a layout is warranted for any Group or Diagram, this is called immediately afterwards. * * @param links The set of links that were recently recomputed, which may need routing. * @param container A Diagram or Group on which the Router will operate. */ routeLinks(links: Set, container: Diagram | Group): void; }