From 501c16f065471185bd9aa2e833bec4d5d661311e Mon Sep 17 00:00:00 2001 From: worksofliam Date: Sat, 15 Mar 2025 22:02:39 -0400 Subject: [PATCH 1/5] Initial work for graphs Signed-off-by: worksofliam --- src/views/cytoscape/index.ts | 149 +++++++++++++++++++++++++++++++++++ src/views/results/index.ts | 23 +++++- 2 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 src/views/cytoscape/index.ts diff --git a/src/views/cytoscape/index.ts b/src/views/cytoscape/index.ts new file mode 100644 index 00000000..f70c67fc --- /dev/null +++ b/src/views/cytoscape/index.ts @@ -0,0 +1,149 @@ +import { ViewColumn, window } from "vscode"; + +type Styles = {[key: string]: string}; + +export interface Element { + data: {id: string, label: string}, + style: Styles +} + +export interface Edge { + data: {id: string, source: string, target: string} +} + +interface NewNode { + label: string, + styles?: Styles, + parent?: string, + data?: any; +} + +const randomId = () => Math.random().toString(36).substring(7); + +export class CytoscapeGraph { + private elementData = new Map(); + private elements: Element[] = []; + private edges: Edge[] = []; + + constructor() {} + + addNode(node: NewNode): string { + const id = randomId(); // TODO: is this unique enough? + + if (node.data) { + this.elementData.set(id, node.data); + } + + this.elements.push({ + data: {id, label: node.label}, + style: node.styles || {} + }); + + if (node.parent) { + this.edges.push({ + data: {id: randomId(), source: node.parent, target: id} + }); + } + + return id; + } + + createView(title: string) { + const webview = window.createWebviewPanel(`c`, title, {viewColumn: ViewColumn.One}, {enableScripts: true, retainContextWhenHidden: true}); + webview.webview.html = this.getHtml(); + + return webview; + } + + private getHtml(): string { + return /*html*/` + + + + + + + + + + + +
+ + + + + + `; + } +} \ No newline at end of file diff --git a/src/views/results/index.ts b/src/views/results/index.ts index 113c2dcd..508c7a96 100644 --- a/src/views/results/index.ts +++ b/src/views/results/index.ts @@ -8,7 +8,7 @@ import { JobManager } from "../../config"; import Document from "../../language/sql/document"; import { ObjectRef, ParsedEmbeddedStatement, StatementGroup, StatementType } from "../../language/sql/types"; import Statement from "../../language/sql/statement"; -import { ExplainTree } from "./explain/nodes"; +import { ExplainNode, ExplainTree } from "./explain/nodes"; import { DoveResultsView, ExplainTreeItem } from "./explain/doveResultsView"; import { DoveNodeView, PropertyNode } from "./explain/doveNodeView"; import { DoveTreeDecorationProvider } from "./explain/doveTreeDecorationProvider"; @@ -17,6 +17,7 @@ import { generateSqlForAdvisedIndexes } from "./explain/advice"; import { updateStatusBar } from "../jobManager/statusBar"; import { ExplainType } from "@ibm/mapepire-js/dist/src/types"; import { DbCache } from "../../language/providers/logic/cache"; +import { CytoscapeGraph } from "../cytoscape"; export type StatementQualifier = "statement" | "update" | "explain" | "onlyexplain" | "json" | "csv" | "cl" | "sql"; @@ -256,6 +257,26 @@ async function runHandler(options?: StatementInfo) { const rootNode = doveResultsView.setRootNode(topLevel); doveNodeView.setNode(rootNode.explainNode); doveTreeDecorationProvider.updateTreeItems(rootNode); + + const graph = new CytoscapeGraph(); + + function addNode(node: ExplainNode, parent?: string) { + const id = graph.addNode({ + label: node.title, + parent: parent, + }); + + if (node.children) { + for (const child of node.children) { + addNode(child, id); + } + } + } + + addNode(topLevel); + + const webview = graph.createView(`Explain Graph`); + } else { vscode.window.showInformationMessage(`No job currently selected.`); } From 1bf06b016e276fdcec8d8a2028c950f1dc66cb0f Mon Sep 17 00:00:00 2001 From: worksofliam Date: Sat, 15 Mar 2025 22:10:04 -0400 Subject: [PATCH 2/5] Click on node to show detail Signed-off-by: worksofliam --- src/views/cytoscape/index.ts | 17 ++++++++++++++--- src/views/results/index.ts | 12 +++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/views/cytoscape/index.ts b/src/views/cytoscape/index.ts index f70c67fc..3f670ecb 100644 --- a/src/views/cytoscape/index.ts +++ b/src/views/cytoscape/index.ts @@ -48,10 +48,17 @@ export class CytoscapeGraph { return id; } - createView(title: string) { + createView(title: string, onNodeSelected: (data: unknown) => void): any { const webview = window.createWebviewPanel(`c`, title, {viewColumn: ViewColumn.One}, {enableScripts: true, retainContextWhenHidden: true}); webview.webview.html = this.getHtml(); + webview.webview.onDidReceiveMessage((message) => { + if (message.command === 'selected') { + const data = this.elementData.get(message.nodeId); + onNodeSelected(data); + } + }, undefined, []); + return webview; } @@ -90,6 +97,7 @@ export class CytoscapeGraph {
diff --git a/src/views/results/index.ts b/src/views/results/index.ts index 508c7a96..1da0b067 100644 --- a/src/views/results/index.ts +++ b/src/views/results/index.ts @@ -254,16 +254,14 @@ async function runHandler(options?: StatementInfo) { explainTree = new ExplainTree(explained.vedata); const topLevel = explainTree.get(); - const rootNode = doveResultsView.setRootNode(topLevel); - doveNodeView.setNode(rootNode.explainNode); - doveTreeDecorationProvider.updateTreeItems(rootNode); - + const graph = new CytoscapeGraph(); function addNode(node: ExplainNode, parent?: string) { const id = graph.addNode({ label: node.title, parent: parent, + data: node, }); if (node.children) { @@ -275,7 +273,11 @@ async function runHandler(options?: StatementInfo) { addNode(topLevel); - const webview = graph.createView(`Explain Graph`); + const webview = graph.createView(`Explain Graph`, (data: ExplainNode) => { + if (data) { + doveNodeView.setNode(data); + } + }); } else { vscode.window.showInformationMessage(`No job currently selected.`); From d81df5905664f06906a109d7a260ed776f3c54e7 Mon Sep 17 00:00:00 2001 From: worksofliam Date: Sat, 15 Mar 2025 22:29:29 -0400 Subject: [PATCH 3/5] Remove legacy view Signed-off-by: worksofliam --- package.json | 15 -- src/views/results/explain/contributes.json | 15 -- src/views/results/explain/doveResultsView.ts | 143 ------------------- src/views/results/explain/icons.ts | 48 +++++++ src/views/results/index.ts | 26 ---- 5 files changed, 48 insertions(+), 199 deletions(-) delete mode 100644 src/views/results/explain/doveResultsView.ts create mode 100644 src/views/results/explain/icons.ts diff --git a/package.json b/package.json index 3836c67a..75a6dab9 100644 --- a/package.json +++ b/package.json @@ -496,12 +496,6 @@ "category": "Db2 for i", "icon": "$(gear)" }, - { - "command": "vscode-db2i.dove.export", - "title": "Export current VE data", - "category": "Db2 for i", - "icon": "$(file)" - }, { "command": "vscode-db2i.dove.node.copy", "title": "Copy value", @@ -735,10 +729,6 @@ "command": "vscode-db2i.dove.editSettings", "when": "vscode-db2i:explaining == true" }, - { - "command": "vscode-db2i.dove.export", - "when": "vscode-db2i:explaining == true" - }, { "command": "vscode-db2i.dove.node.copy", "when": "never" @@ -835,11 +825,6 @@ "group": "navigation@1", "when": "view == vscode-db2i.dove.nodes" }, - { - "command": "vscode-db2i.dove.export", - "group": "navigation@2", - "when": "view == vscode-db2i.dove.nodes" - }, { "command": "vscode-db2i.dove.close", "group": "navigation@3", diff --git a/src/views/results/explain/contributes.json b/src/views/results/explain/contributes.json index 69383210..2d73944d 100644 --- a/src/views/results/explain/contributes.json +++ b/src/views/results/explain/contributes.json @@ -106,12 +106,6 @@ "category": "Db2 for i", "icon": "$(gear)" }, - { - "command": "vscode-db2i.dove.export", - "title": "Export current VE data", - "category": "Db2 for i", - "icon": "$(file)" - }, { "command": "vscode-db2i.dove.node.copy", "title": "Copy value", @@ -133,10 +127,6 @@ "command": "vscode-db2i.dove.editSettings", "when": "vscode-db2i:explaining == true" }, - { - "command": "vscode-db2i.dove.export", - "when": "vscode-db2i:explaining == true" - }, { "command": "vscode-db2i.dove.node.copy", "when": "never" @@ -153,11 +143,6 @@ "group": "navigation@1", "when": "view == vscode-db2i.dove.nodes" }, - { - "command": "vscode-db2i.dove.export", - "group": "navigation@2", - "when": "view == vscode-db2i.dove.nodes" - }, { "command": "vscode-db2i.dove.close", "group": "navigation@3", diff --git a/src/views/results/explain/doveResultsView.ts b/src/views/results/explain/doveResultsView.ts deleted file mode 100644 index fc9285a3..00000000 --- a/src/views/results/explain/doveResultsView.ts +++ /dev/null @@ -1,143 +0,0 @@ -import * as vscode from "vscode"; -import { CancellationToken, Event, EventEmitter, ProviderResult, TreeView, TreeDataProvider, TreeItem, TreeItemCollapsibleState, commands, ThemeIcon } from "vscode"; -import { ExplainNode } from "./nodes"; -import { toDoveTreeDecorationProviderUri } from "./doveTreeDecorationProvider"; - -/** - * Icon labels as defined by the API, along with the name of the icon to display. - * Not surprisingly, the reference link does not provide a complete list of icons. - * TODO: Add missing icons - * @see https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qqqvexpl.html#icon_labels - * @see https://code.visualstudio.com/api/references/icons-in-labels - */ -const icons = { - "Bitmap Merge": `merge`, - "Cache": ``, - "Cache Probe": ``, - "Delete": `trash`, - "Distinct": `list-flat`, - "Dynamic Bitmap": `symbol-misc`, - "Encoded Vector Index": `symbol-reference`, - "Encoded Vector Index, Parallel": `symbol-reference`, - "Final Select": `selection`, - "Hash Grouping": `group-by-ref-type`, - "Hash Join": `add`, - "Hash Scan": `search`, - "Index Grouping": `group-by-ref-type`, - "Index Scan - Key Positioning": `key`, - "Index Scan - Key Positioning, Parallel": `key`, - "Index Scan - Key Selection": `key`, - "Index Scan - Key Selection, Parallel": `key`, - "Insert": `insert`, - "Nested Loop Join": `add`, - "Select": `selection`, - "Skip Sequential Table Scan": `list-unordered`, - "Skip Sequential Table Scan, Parallel": `list-unordered`, - "Sort": `sort-precedence`, - "Sorted List Scan": `list-ordered`, - "Subquery Merge": `merge`, - "Table Probe": `list-selection`, - "Table Scan": `search`, - "Table Scan, Parallel": `search`, - "Temporary Distinct Hash Table": `new-file`, - "Temporary Hash Table": `new-file`, - "Temporary Index": `new-file`, - "Temporary Sorted List": `list-ordered`, - "Temporary Table": `new-file`, - "Union Merge": `merge`, - "User Defined Table Function": `symbol-function`, - "Unknown": `question`, - "Update": `replace`, - "VALUES LIST": `list-flat`, -} - -type ChangeTreeDataEventType = ExplainTreeItem | undefined | null | void; - -export class DoveResultsView implements TreeDataProvider { - private _onDidChangeTreeData: EventEmitter = new EventEmitter(); - readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; - - private topNode: ExplainTreeItem; - - private treeView: TreeView; - - constructor() { - this.treeView = vscode.window.createTreeView(`vscode-db2i.dove.nodes`, { treeDataProvider: this, showCollapseAll: true }); - } - - public getTreeView(): TreeView { - return this.treeView; - } - - setRootNode(topNode: ExplainNode): ExplainTreeItem { - this.topNode = new ExplainTreeItem(topNode); - this._onDidChangeTreeData.fire(); - - // Show tree in the view - commands.executeCommand(`setContext`, `vscode-db2i:explaining`, true); - // Ensure that the tree is positioned such that the first element is visible - this.treeView.reveal(this.topNode, { select: false }); - return this.topNode; - } - getRootNode(): ExplainTreeItem { - return this.topNode; - } - - getRootExplainNode(): ExplainNode { - return this.topNode.explainNode; - } - - close(): void { - commands.executeCommand(`setContext`, `vscode-db2i:explaining`, false); - } - - getTreeItem(element: ExplainTreeItem): ExplainTreeItem | Thenable { - return element; - } - - getChildren(element?: ExplainTreeItem): ProviderResult { - if (element) { - return element.getChildren(); - } else if (this.topNode) { - return [this.topNode]; - } else { - return []; - } - } - - getParent?(element: any) { - throw new Error("Method not implemented."); - } - - resolveTreeItem?(item: TreeItem, element: any, token: CancellationToken): ProviderResult { - throw new Error("Method not implemented."); - } -} - -export class ExplainTreeItem extends TreeItem { - explainNode: ExplainNode; - private children: ExplainTreeItem[]; - - constructor(node: ExplainNode) { - super(node.title, node.childrenNodes > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None); - this.explainNode = node; - this.contextValue = `explainTreeItem`; - - // If the node is associated with a DB object, display the qualified object name in the description - if (node.objectSchema && node.objectName) { - this.description = node.objectSchema + `.` + node.objectName; - } - - // TODO: ideally the tooltip would be built using a MarkdownString, but regardless of everything tried, 'Loading...' is always displayed - this.tooltip = [node.title, node.tooltipProps.map(prop => prop.title + `: ` + prop.value).join(`\n`), ``].join(`\n`); - this.resourceUri = toDoveTreeDecorationProviderUri(node.highlights); - this.iconPath = new ThemeIcon(icons[node.title] || `server-process`, node.highlights.getPriorityColor()); // `circle-outline` - } - - getChildren(): ExplainTreeItem[] { - if (!this.children) { - this.children = this.explainNode.children.map(c => new ExplainTreeItem(c)); - } - return this.children; - } -} \ No newline at end of file diff --git a/src/views/results/explain/icons.ts b/src/views/results/explain/icons.ts new file mode 100644 index 00000000..65cb4115 --- /dev/null +++ b/src/views/results/explain/icons.ts @@ -0,0 +1,48 @@ + +/** + * Icon labels as defined by the API, along with the name of the icon to display. + * Not surprisingly, the reference link does not provide a complete list of icons. + * TODO: Add missing icons + * @see https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qqqvexpl.html#icon_labels + * @see https://code.visualstudio.com/api/references/icons-in-labels + */ +const icons = { + "Bitmap Merge": `merge`, + "Cache": ``, + "Cache Probe": ``, + "Delete": `trash`, + "Distinct": `list-flat`, + "Dynamic Bitmap": `symbol-misc`, + "Encoded Vector Index": `symbol-reference`, + "Encoded Vector Index, Parallel": `symbol-reference`, + "Final Select": `selection`, + "Hash Grouping": `group-by-ref-type`, + "Hash Join": `add`, + "Hash Scan": `search`, + "Index Grouping": `group-by-ref-type`, + "Index Scan - Key Positioning": `key`, + "Index Scan - Key Positioning, Parallel": `key`, + "Index Scan - Key Selection": `key`, + "Index Scan - Key Selection, Parallel": `key`, + "Insert": `insert`, + "Nested Loop Join": `add`, + "Select": `selection`, + "Skip Sequential Table Scan": `list-unordered`, + "Skip Sequential Table Scan, Parallel": `list-unordered`, + "Sort": `sort-precedence`, + "Sorted List Scan": `list-ordered`, + "Subquery Merge": `merge`, + "Table Probe": `list-selection`, + "Table Scan": `search`, + "Table Scan, Parallel": `search`, + "Temporary Distinct Hash Table": `new-file`, + "Temporary Hash Table": `new-file`, + "Temporary Index": `new-file`, + "Temporary Sorted List": `list-ordered`, + "Temporary Table": `new-file`, + "Union Merge": `merge`, + "User Defined Table Function": `symbol-function`, + "Unknown": `question`, + "Update": `replace`, + "VALUES LIST": `list-flat`, +} \ No newline at end of file diff --git a/src/views/results/index.ts b/src/views/results/index.ts index 1da0b067..1ae6da77 100644 --- a/src/views/results/index.ts +++ b/src/views/results/index.ts @@ -9,7 +9,6 @@ import Document from "../../language/sql/document"; import { ObjectRef, ParsedEmbeddedStatement, StatementGroup, StatementType } from "../../language/sql/types"; import Statement from "../../language/sql/statement"; import { ExplainNode, ExplainTree } from "./explain/nodes"; -import { DoveResultsView, ExplainTreeItem } from "./explain/doveResultsView"; import { DoveNodeView, PropertyNode } from "./explain/doveNodeView"; import { DoveTreeDecorationProvider } from "./explain/doveTreeDecorationProvider"; import { ResultSetPanelProvider } from "./resultSetPanelProvider"; @@ -42,8 +41,6 @@ export function setCancelButtonVisibility(visible: boolean) { let resultSetProvider = new ResultSetPanelProvider(); let explainTree: ExplainTree; -let doveResultsView = new DoveResultsView(); -let doveResultsTreeView: TreeView = doveResultsView.getTreeView(); let doveNodeView = new DoveNodeView(); let doveNodeTreeView: TreeView = doveNodeView.getTreeView(); let doveTreeDecorationProvider = new DoveTreeDecorationProvider(); // Self-registers as a tree decoration providor @@ -52,7 +49,6 @@ export function initialise(context: vscode.ExtensionContext) { setCancelButtonVisibility(false); context.subscriptions.push( - doveResultsTreeView, doveNodeTreeView, vscode.window.registerWebviewViewProvider(`vscode-db2i.resultset`, resultSetProvider, { @@ -91,17 +87,6 @@ export function initialise(context: vscode.ExtensionContext) { } }), - vscode.commands.registerCommand(`vscode-db2i.dove.close`, () => { - doveResultsView.close(); - doveNodeView.close(); - }), - - vscode.commands.registerCommand(`vscode-db2i.dove.displayDetails`, (explainTreeItem: ExplainTreeItem) => { - // When the user clicks for details of a node in the tree, set the focus to that node as a visual indicator tying it to the details tree - doveResultsTreeView.reveal(explainTreeItem, { select: false, focus: true, expand: true }); - doveNodeView.setNode(explainTreeItem.explainNode); - }), - vscode.commands.registerCommand(`vscode-db2i.dove.node.copy`, (propertyNode: PropertyNode) => { if (propertyNode.description && typeof propertyNode.description === `string`) { vscode.env.clipboard.writeText(propertyNode.description); @@ -117,15 +102,6 @@ export function initialise(context: vscode.ExtensionContext) { vscode.commands.executeCommand('workbench.action.openSettings', 'vscode-db2i.visualExplain'); }), - vscode.commands.registerCommand(`vscode-db2i.dove.export`, () => { - vscode.workspace.openTextDocument({ - language: `json`, - content: JSON.stringify(doveResultsView.getRootExplainNode(), null, 2) - }).then(doc => { - vscode.window.showTextDocument(doc); - }); - }), - vscode.commands.registerCommand(`vscode-db2i.dove.generateSqlForAdvisedIndexes`, () => { const scriptContent = generateSqlForAdvisedIndexes(explainTree); @@ -158,8 +134,6 @@ async function runHandler(options?: StatementInfo) { const optionsIsValid = (options?.content !== undefined); let editor = vscode.window.activeTextEditor; - vscode.commands.executeCommand('vscode-db2i.dove.close'); - if (optionsIsValid || (editor && editor.document.languageId === `sql`)) { let chosenView = resultSetProvider; From eb0d8ea08f01d04702dc4cbac6d1b31a564280fe Mon Sep 17 00:00:00 2001 From: Jonathan Zak Date: Wed, 23 Jul 2025 10:18:40 -0400 Subject: [PATCH 4/5] visual explain redesign --- media/explain/borderAndIconDraw.js | 91 +++++++++ media/explain/cytoscape.min.js | 31 +++ media/explain/explain.css | 51 +++++ media/explain/explain.js | 126 ++++++++++++ media/explain/graphUtils.js | 113 +++++++++++ package-lock.json | 10 + package.json | 17 ++ src/contextProvider.ts | 16 ++ src/extension.ts | 2 + src/views/cytoscape/index.ts | 190 ++++++++---------- src/views/results/explain/contributes.json | 15 ++ src/views/results/explain/doveResultsView.ts | 143 +++++++++++++ .../explain/doveTreeDecorationProvider.ts | 2 +- src/views/results/explain/icons.ts | 153 ++++++++++---- src/views/results/explain/nodes.ts | 19 +- src/views/results/index.ts | 34 +++- 16 files changed, 861 insertions(+), 152 deletions(-) create mode 100644 media/explain/borderAndIconDraw.js create mode 100644 media/explain/cytoscape.min.js create mode 100644 media/explain/explain.css create mode 100644 media/explain/explain.js create mode 100644 media/explain/graphUtils.js create mode 100644 src/contextProvider.ts create mode 100644 src/views/results/explain/doveResultsView.ts diff --git a/media/explain/borderAndIconDraw.js b/media/explain/borderAndIconDraw.js new file mode 100644 index 00000000..ae21ab01 --- /dev/null +++ b/media/explain/borderAndIconDraw.js @@ -0,0 +1,91 @@ +// @ts-nocheck +import { + getNodeTopLeftAbsolute, + getTopLeftForBorder, + getBorderWidthAndHeight, +} from "./graphUtils.js"; + +export function deleteAllBorders() { + document.querySelectorAll(".border").forEach((el) => el.remove()); +} + +const iconMap = window.iconMap; + +const getCodiconClass = (label) => { + const className = iconMap[label]; + return className !== undefined ? `codicon-${className}` : ""; +}; + +function drawNodeIcon(fontSize, color, label) { + const icon = document.createElement("i"); + const codiconClass = getCodiconClass(label); + icon.className = `codicon ${codiconClass}`; + Object.assign(icon.style, { + fontSize: `${fontSize}px`, + color, + height: "fit-content", + }); + return icon; +} + +export function drawBorderAndIconForEachExplainNode( + cy, + windowPadding +) { + const paddingX = 30; + const paddingY = 10; + const iconGap = 20; + const borderRadius = 10; + const iconColor = "#007acc"; + + let minIconSize = 50; + cy.nodes().forEach((node) => { + const nodeW = node.renderedWidth(); + const iconSize = nodeW / 2; + minIconSize = Math.min(minIconSize, iconSize); + }); + + + cy.nodes().forEach((node) => { + const nodeW = node.renderedWidth(); + const nodeH = node.renderedHeight(); + + const nodeTopLeft = getNodeTopLeftAbsolute(node, cy); + + const topLeft = getTopLeftForBorder( + nodeTopLeft.x, + nodeTopLeft.y, + paddingX, + paddingY, + minIconSize, + iconGap + ); + const dimensions = getBorderWidthAndHeight( + paddingX, + nodeW, + paddingY, + nodeH, + minIconSize, + iconGap + ); + + const border = document.createElement("div"); + border.className = "border"; + + Object.assign(border.style, { + width: `${dimensions.width}px`, + height: `${dimensions.height}px`, + position: "absolute", + top: `${topLeft.y}px`, + left: `${topLeft.x}px`, + display: "flex", + justifyContent: "center", + paddingTop: `${paddingY}px`, + borderRadius: `${borderRadius}px`, + borderColor: "transparent" + }); + + border.appendChild(drawNodeIcon(minIconSize, iconColor, node.data().label)); + document.body.appendChild(border); + }); +} diff --git a/media/explain/cytoscape.min.js b/media/explain/cytoscape.min.js new file mode 100644 index 00000000..81241174 --- /dev/null +++ b/media/explain/cytoscape.min.js @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2016-2025, The Cytoscape Consortium. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the “Software”), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).cytoscape=t()}(this,(function(){"use strict";function e(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return o=e.done,e},e:function(e){s=!0,i=e},f:function(){try{o||null==n.return||n.return()}finally{if(s)throw i}}}}function a(e,t,n){return(t=s(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,i,o,s=[],l=!0,u=!1;try{if(i=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=i.call(n)).done)&&(s.push(r.value),s.length!==t);l=!0);}catch(e){u=!0,a=e}finally{try{if(!l&&null!=n.return&&(o=n.return(),Object(o)!==o))return}finally{if(u)throw a}}return s}}(e,t)||u(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(t){return function(t){if(Array.isArray(t))return e(t)}(t)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(t)||u(t)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function s(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t);if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e,"string");return"symbol"==typeof t?t:t+""}function l(e){return l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},l(e)}function u(t,n){if(t){if("string"==typeof t)return e(t,n);var r={}.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?e(t,n):void 0}}var c="undefined"==typeof window?null:window,d=c?c.navigator:null;c&&c.document;var h,f,p,v,g,y,m,b,x,w,E,k,T,C,P,S,B,D,_,A,M,R,I,N,L,z,O,V,F=l(""),j=l({}),X=l((function(){})),q="undefined"==typeof HTMLElement?"undefined":l(HTMLElement),Y=function(e){return e&&e.instanceString&&U(e.instanceString)?e.instanceString():null},W=function(e){return null!=e&&l(e)==F},U=function(e){return null!=e&&l(e)===X},H=function(e){return!$(e)&&(Array.isArray?Array.isArray(e):null!=e&&e instanceof Array)},K=function(e){return null!=e&&l(e)===j&&!H(e)&&e.constructor===Object},G=function(e){return null!=e&&l(e)===l(1)&&!isNaN(e)},Z=function(e){return"undefined"===q?void 0:null!=e&&e instanceof HTMLElement},$=function(e){return Q(e)||J(e)},Q=function(e){return"collection"===Y(e)&&e._private.single},J=function(e){return"collection"===Y(e)&&!e._private.single},ee=function(e){return"core"===Y(e)},te=function(e){return"stylesheet"===Y(e)},ne=function(e){return null==e||!(""!==e&&!e.match(/^\s+$/))},re=function(e){return function(e){return null!=e&&l(e)===j}(e)&&U(e.then)},ae=function(e,t){t||(t=function(){if(1===arguments.length)return arguments[0];if(0===arguments.length)return"undefined";for(var e=[],t=0;tt?1:0},ge=null!=Object.assign?Object.assign.bind(Object):function(e){for(var t=arguments,n=1;n255)return;t.push(Math.floor(i))}var o=r[1]||r[2]||r[3],s=r[1]&&r[2]&&r[3];if(o&&!s)return;var l=n[4];if(void 0!==l){if((l=parseFloat(l))<0||l>1)return;t.push(l)}}return t}(e)||function(e){var t,n,r,a,i,o,s,l;function u(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+(t-e)*(2/3-n)*6:e}var c=new RegExp("^"+fe+"$").exec(e);if(c){if((n=parseInt(c[1]))<0?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,(r=parseFloat(c[2]))<0||r>100)return;if(r/=100,(a=parseFloat(c[3]))<0||a>100)return;if(a/=100,void 0!==(i=c[4])&&((i=parseFloat(i))<0||i>1))return;if(0===r)o=s=l=Math.round(255*a);else{var d=a<.5?a*(1+r):a+r-a*r,h=2*a-d;o=Math.round(255*u(h,d,n+1/3)),s=Math.round(255*u(h,d,n)),l=Math.round(255*u(h,d,n-1/3))}t=[o,s,l,i]}return t}(e)},me={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},be=function(e){for(var t=e.map,n=e.keys,r=n.length,a=0;a=o||t<0||g&&e-p>=c}function x(){var e=t();if(b(e))return w(e);h=setTimeout(x,function(e){var t=o-(e-f);return g?a(t,c-(e-p)):t}(e))}function w(e){return h=void 0,y&&l?m(e):(l=u=void 0,d)}function E(){var e=t(),n=b(e);if(l=arguments,u=this,f=e,n){if(void 0===h)return function(e){return p=e,h=setTimeout(x,o),v?m(e):d}(f);if(g)return clearTimeout(h),h=setTimeout(x,o),m(f)}return void 0===h&&(h=setTimeout(x,o)),d}return o=n(o)||0,e(s)&&(v=!!s.leading,c=(g="maxWait"in s)?r(n(s.maxWait)||0,o):c,y="trailing"in s?!!s.trailing:y),E.cancel=function(){void 0!==h&&clearTimeout(h),p=0,l=f=u=h=void 0},E.flush=function(){return void 0===h?d:w(t())},E},O}(),_e=Ee(De),Ae=c?c.performance:null,Me=Ae&&Ae.now?function(){return Ae.now()}:function(){return Date.now()},Re=function(){if(c){if(c.requestAnimationFrame)return function(e){c.requestAnimationFrame(e)};if(c.mozRequestAnimationFrame)return function(e){c.mozRequestAnimationFrame(e)};if(c.webkitRequestAnimationFrame)return function(e){c.webkitRequestAnimationFrame(e)};if(c.msRequestAnimationFrame)return function(e){c.msRequestAnimationFrame(e)}}return function(e){e&&setTimeout((function(){e(Me())}),1e3/60)}}(),Ie=function(e){return Re(e)},Ne=Me,Le=9261,ze=5381,Oe=function(e){for(var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Le;!(t=e.next()).done;)n=65599*n+t.value|0;return n},Ve=function(e){return 65599*(arguments.length>1&&void 0!==arguments[1]?arguments[1]:Le)+e|0},Fe=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ze;return(t<<5)+t+e|0},je=function(e){return 2097152*e[0]+e[1]},Xe=function(e,t){return[Ve(e[0],t[0]),Fe(e[1],t[1])]},qe=function(e,t){var n={value:0,done:!1},r=0,a=e.length;return Oe({next:function(){return r=0;r--)e[r]===t&&e.splice(r,1)},ct=function(e){e.splice(0,e.length)},dt=function(e,t,n){return n&&(t=se(n,t)),e[t]},ht=function(e,t,n,r){n&&(t=se(n,t)),e[t]=r},ft="undefined"!=typeof Map?Map:function(){return n((function e(){t(this,e),this._obj={}}),[{key:"set",value:function(e,t){return this._obj[e]=t,this}},{key:"delete",value:function(e){return this._obj[e]=void 0,this}},{key:"clear",value:function(){this._obj={}}},{key:"has",value:function(e){return void 0!==this._obj[e]}},{key:"get",value:function(e){return this._obj[e]}}])}(),pt=function(){return n((function e(n){if(t(this,e),this._obj=Object.create(null),this.size=0,null!=n){var r;r=null!=n.instanceString&&n.instanceString()===this.instanceString()?n.toArray():n;for(var a=0;a2&&void 0!==arguments[2])||arguments[2];if(void 0!==e&&void 0!==t&&ee(e)){var r=t.group;if(null==r&&(r=t.data&&null!=t.data.source&&null!=t.data.target?"edges":"nodes"),"nodes"===r||"edges"===r){this.length=1,this[0]=this;var a=this._private={cy:e,single:!0,data:t.data||{},position:t.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:r,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!t.selected,selectable:void 0===t.selectable||!!t.selectable,locked:!!t.locked,grabbed:!1,grabbable:void 0===t.grabbable||!!t.grabbable,pannable:void 0===t.pannable?"edges"===r:!!t.pannable,active:!1,classes:new vt,animation:{current:[],queue:[]},rscratch:{},scratch:t.scratch||{},edges:[],children:[],parent:t.parent&&t.parent.isNode()?t.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(null==a.position.x&&(a.position.x=0),null==a.position.y&&(a.position.y=0),t.renderedPosition){var i=t.renderedPosition,o=e.pan(),s=e.zoom();a.position={x:(i.x-o.x)/s,y:(i.y-o.y)/s}}var l=[];H(t.classes)?l=t.classes:W(t.classes)&&(l=t.classes.split(/\s+/));for(var u=0,c=l.length;ut?1:0},u=function(e,t,a,i,o){var s;if(null==a&&(a=0),null==o&&(o=n),a<0)throw new Error("lo must be non-negative");for(null==i&&(i=e.length);an;0<=n?t++:t--)u.push(t);return u}.apply(this).reverse()).length;iv;0<=v?++h:--h)g.push(i(e,r));return g},p=function(e,t,r,a){var i,o,s;for(null==a&&(a=n),i=e[r];r>t&&a(i,o=e[s=r-1>>1])<0;)e[r]=o,r=s;return e[r]=i},v=function(e,t,r){var a,i,o,s,l;for(null==r&&(r=n),i=e.length,l=t,o=e[t],a=2*t+1;a0;){var w=y.pop(),E=v(w),k=w.id();if(d[k]=E,E!==1/0)for(var T=w.neighborhood().intersect(f),C=0;C0)for(n.unshift(t);c[a];){var i=c[a];n.unshift(i.edge),n.unshift(i.node),a=(r=i.node).id()}return o.spawn(n)}}}},Dt={kruskal:function(e){e=e||function(e){return 1};for(var t=this.byGroup(),n=t.nodes,r=t.edges,a=n.length,i=new Array(a),o=n,s=function(e){for(var t=0;t0;){if(l=v.pop(),u=l.id(),g.delete(u),w++,u===d){for(var E=[],k=a,T=d,C=m[T];E.unshift(k),null!=C&&E.unshift(C),null!=(k=y[T]);)C=m[T=k.id()];return{found:!0,distance:h[u],path:this.spawn(E),steps:w}}p[u]=!0;for(var P=l._private.edges,S=0;SP&&(f[C]=P,y[C]=T,m[C]=x),!a){var S=T*u+k;!a&&f[S]>P&&(f[S]=P,y[S]=k,m[S]=x)}}}for(var B=0;B1&&void 0!==arguments[1]?arguments[1]:i,r=[],a=m(e);;){if(null==a)return t.spawn();var o=y(a),l=o.edge,u=o.pred;if(r.unshift(a[0]),a.same(n)&&r.length>0)break;null!=l&&r.unshift(l),a=u}return s.spawn(r)},hasNegativeWeightCycle:p,negativeWeightCycles:v}}},Lt=Math.sqrt(2),zt=function(e,t,n){0===n.length&&tt("Karger-Stein must be run on a connected (sub)graph");for(var r=n[e],a=r[1],i=r[2],o=t[a],s=t[i],l=n,u=l.length-1;u>=0;u--){var c=l[u],d=c[1],h=c[2];(t[d]===o&&t[h]===s||t[d]===s&&t[h]===o)&&l.splice(u,1)}for(var f=0;fr;){var a=Math.floor(Math.random()*t.length);t=zt(a,e,t),n--}return t},Vt={kargerStein:function(){var e=this,t=this.byGroup(),n=t.nodes,r=t.edges;r.unmergeBy((function(e){return e.isLoop()}));var a=n.length,i=r.length,o=Math.ceil(Math.pow(Math.log(a)/Math.LN2,2)),s=Math.floor(a/Lt);if(!(a<2)){for(var l=[],u=0;u0?1:e<0?-1:0},Ut=function(e,t){return Math.sqrt(Ht(e,t))},Ht=function(e,t){var n=t.x-e.x,r=t.y-e.y;return n*n+r*r},Kt=function(e){for(var t=e.length,n=0,r=0;r=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(null!=e.w&&null!=e.h&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},Jt=function(e,t,n){e.x1=Math.min(e.x1,t),e.x2=Math.max(e.x2,t),e.w=e.x2-e.x1,e.y1=Math.min(e.y1,n),e.y2=Math.max(e.y2,n),e.h=e.y2-e.y1},en=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;return e.x1-=t,e.x2+=t,e.y1-=t,e.y2+=t,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},tn=function(e){var t,n,r,a,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[0];if(1===o.length)t=n=r=a=o[0];else if(2===o.length)t=r=o[0],a=n=o[1];else if(4===o.length){var s=i(o,4);t=s[0],n=s[1],r=s[2],a=s[3]}return e.x1-=a,e.x2+=n,e.y1-=t,e.y2+=r,e.w=e.x2-e.x1,e.h=e.y2-e.y1,e},nn=function(e,t){e.x1=t.x1,e.y1=t.y1,e.x2=t.x2,e.y2=t.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1},rn=function(e,t){return!(e.x1>t.x2)&&(!(t.x1>e.x2)&&(!(e.x2t.y2)&&!(t.y1>e.y2)))))))},an=function(e,t,n){return e.x1<=t&&t<=e.x2&&e.y1<=n&&n<=e.y2},on=null!==(Ct=Math.hypot)&&void 0!==Ct?Ct:function(e,t){return Math.sqrt(e*e+t*t)};function sn(e,t,n,r,a,i){var o=function(e,t){if(e.length<3)throw new Error("Need at least 3 vertices");var n=function(e,t){return{x:e.x+t.x,y:e.y+t.y}},r=function(e,t){return{x:e.x-t.x,y:e.y-t.y}},a=function(e,t){return{x:e.x*t,y:e.y*t}},i=function(e,t){return e.x*t.y-e.y*t.x},o=function(e,t,o,s){var l=r(t,e),u=r(s,o),c=i(l,u);if(Math.abs(c)<1e-9)return n(e,a(l,.5));var d=i(r(o,e),u)/c;return n(e,a(l,d))},s=e.map((function(e){return{x:e.x,y:e.y}}));(function(e){for(var t=0,n=0;n7&&void 0!==arguments[7]?arguments[7]:"auto",c="auto"===u?Sn(a,i):u,d=a/2,h=i/2,f=(c=Math.min(c,d,h))!==d,p=c!==h;if(f){var v=r-h-o;if((s=xn(e,t,n,r,n-d+c-o,v,n+d-c+o,v,!1)).length>0)return s}if(p){var g=n+d+o;if((s=xn(e,t,n,r,g,r-h+c-o,g,r+h-c+o,!1)).length>0)return s}if(f){var y=r+h+o;if((s=xn(e,t,n,r,n-d+c-o,y,n+d-c+o,y,!1)).length>0)return s}if(p){var m=n-d-o;if((s=xn(e,t,n,r,m,r-h+c-o,m,r+h-c+o,!1)).length>0)return s}var b=n-d+c,x=r-h+c;if((l=mn(e,t,n,r,b,x,c+o)).length>0&&l[0]<=b&&l[1]<=x)return[l[0],l[1]];var w=n+d-c,E=r-h+c;if((l=mn(e,t,n,r,w,E,c+o)).length>0&&l[0]>=w&&l[1]<=E)return[l[0],l[1]];var k=n+d-c,T=r+h-c;if((l=mn(e,t,n,r,k,T,c+o)).length>0&&l[0]>=k&&l[1]>=T)return[l[0],l[1]];var C=n-d+c,P=r+h-c;return(l=mn(e,t,n,r,C,P,c+o)).length>0&&l[0]<=C&&l[1]>=P?[l[0],l[1]]:[]},un=function(e,t,n,r,a,i,o){var s=o,l=Math.min(n,a),u=Math.max(n,a),c=Math.min(r,i),d=Math.max(r,i);return l-s<=e&&e<=u+s&&c-s<=t&&t<=d+s},cn=function(e,t,n,r,a,i,o,s,l){var u=Math.min(n,o,a)-l,c=Math.max(n,o,a)+l,d=Math.min(r,s,i)-l,h=Math.max(r,s,i)+l;return!(ec||th)},dn=function(e,t,n,r,a,i,o,s){var l=[];!function(e,t,n,r,a){var i,o,s,l,u,c,d,h;0===e&&(e=1e-5),s=-27*(r/=e)+(t/=e)*(9*(n/=e)-t*t*2),i=(o=(3*n-t*t)/9)*o*o+(s/=54)*s,a[1]=0,d=t/3,i>0?(u=(u=s+Math.sqrt(i))<0?-Math.pow(-u,1/3):Math.pow(u,1/3),c=(c=s-Math.sqrt(i))<0?-Math.pow(-c,1/3):Math.pow(c,1/3),a[0]=-d+u+c,d+=(u+c)/2,a[4]=a[2]=-d,d=Math.sqrt(3)*(-c+u)/2,a[3]=d,a[5]=-d):(a[5]=a[3]=0,0===i?(h=s<0?-Math.pow(-s,1/3):Math.pow(s,1/3),a[0]=2*h-d,a[4]=a[2]=-(h+d)):(l=(o=-o)*o*o,l=Math.acos(s/Math.sqrt(l)),h=2*Math.sqrt(o),a[0]=-d+h*Math.cos(l/3),a[2]=-d+h*Math.cos((l+2*Math.PI)/3),a[4]=-d+h*Math.cos((l+4*Math.PI)/3)))}(1*n*n-4*n*a+2*n*o+4*a*a-4*a*o+o*o+r*r-4*r*i+2*r*s+4*i*i-4*i*s+s*s,9*n*a-3*n*n-3*n*o-6*a*a+3*a*o+9*r*i-3*r*r-3*r*s-6*i*i+3*i*s,3*n*n-6*n*a+n*o-n*e+2*a*a+2*a*e-o*e+3*r*r-6*r*i+r*s-r*t+2*i*i+2*i*t-s*t,1*n*a-n*n+n*e-a*e+r*i-r*r+r*t-i*t,l);for(var u=[],c=0;c<6;c+=2)Math.abs(l[c+1])<1e-7&&l[c]>=0&&l[c]<=1&&u.push(l[c]);u.push(1),u.push(0);for(var d,h,f,p=-1,v=0;v=0?fl?(e-a)*(e-a)+(t-i)*(t-i):u-d},fn=function(e,t,n){for(var r,a,i,o,s=0,l=0;l=e&&e>=i||r<=e&&e<=i))continue;(e-r)/(i-r)*(o-a)+a>t&&s++}return s%2!=0},pn=function(e,t,n,r,a,i,o,s,l){var u,c=new Array(n.length);null!=s[0]?(u=Math.atan(s[1]/s[0]),s[0]<0?u+=Math.PI/2:u=-u-Math.PI/2):u=s;for(var d,h=Math.cos(-u),f=Math.sin(-u),p=0;p0){var v=gn(c,-l);d=vn(v)}else d=c;return fn(e,t,d)},vn=function(e){for(var t,n,r,a,i,o,s,l,u=new Array(e.length/2),c=0;c=0&&p<=1&&g.push(p),v>=0&&v<=1&&g.push(v),0===g.length)return[];var y=g[0]*s[0]+e,m=g[0]*s[1]+t;return g.length>1?g[0]==g[1]?[y,m]:[y,m,g[1]*s[0]+e,g[1]*s[1]+t]:[y,m]},bn=function(e,t,n){return t<=e&&e<=n||n<=e&&e<=t?e:e<=t&&t<=n||n<=t&&t<=e?t:n},xn=function(e,t,n,r,a,i,o,s,l){var u=e-a,c=n-e,d=o-a,h=t-i,f=r-t,p=s-i,v=d*h-p*u,g=c*h-f*u,y=p*c-d*f;if(0!==y){var m=v/y,b=g/y,x=-.001;return x<=m&&m<=1.001&&x<=b&&b<=1.001||l?[e+m*c,t+m*f]:[]}return 0===v||0===g?bn(e,n,o)===o?[o,s]:bn(e,n,a)===a?[a,i]:bn(a,o,n)===n?[n,r]:[]:[]},wn=function(e,t,n,r,a){var i=[],o=r/2,s=a/2,l=t,u=n;i.push({x:l+o*e[0],y:u+s*e[1]});for(var c=1;c0){var m=gn(v,-s);u=vn(m)}else u=v}else u=n;for(var b=0;bu&&(u=t)},d=function(e){return l[e]},h=0;h0?b.edgesTo(m)[0]:m.edgesTo(b)[0];var w=r(x);m=m.id(),u[m]>u[v]+w&&(u[m]=u[v]+w,h.nodes.indexOf(m)<0?h.push(m):h.updateItem(m),l[m]=0,n[m]=[]),u[m]==u[v]+w&&(l[m]=l[m]+l[v],n[m].push(v))}else for(var E=0;E0;){for(var P=t.pop(),S=0;S0&&o.push(n[s]);0!==o.length&&a.push(r.collection(o))}return a}(c,l,t,r);return b=function(e){for(var t=0;t5&&void 0!==arguments[5]?arguments[5]:Gn,o=r,s=0;s=2?tr(e,t,n,0,Qn,Jn):tr(e,t,n,0,$n)},squaredEuclidean:function(e,t,n){return tr(e,t,n,0,Qn)},manhattan:function(e,t,n){return tr(e,t,n,0,$n)},max:function(e,t,n){return tr(e,t,n,-1/0,er)}};function rr(e,t,n,r,a,i){var o;return o=U(e)?e:nr[e]||nr.euclidean,0===t&&U(e)?o(a,i):o(t,n,r,a,i)}nr["squared-euclidean"]=nr.squaredEuclidean,nr.squaredeuclidean=nr.squaredEuclidean;var ar=lt({k:2,m:2,sensitivityThreshold:1e-4,distance:"euclidean",maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),ir=function(e){return ar(e)},or=function(e,t,n,r,a){var i="kMedoids"!==a?function(e){return n[e]}:function(e){return r[e](n)},o=n,s=t;return rr(e,r.length,i,(function(e){return r[e](t)}),o,s)},sr=function(e,t,n){for(var r=n.length,a=new Array(r),i=new Array(r),o=new Array(t),s=null,l=0;ln)return!1}return!0},hr=function(e,t,n){for(var r=0;ra&&(a=t[l][u],i=u);o[i].push(e[l])}for(var c=0;c=a.threshold||"dendrogram"===a.mode&&1===e.length)return!1;var f,p=t[o],v=t[r[o]];f="dendrogram"===a.mode?{left:p,right:v,key:p.key}:{value:p.value.concat(v.value),key:p.key},e[p.index]=f,e.splice(v.index,1),t[p.key]=f;for(var g=0;gn[v.key][y.key]&&(i=n[v.key][y.key])):"max"===a.linkage?(i=n[p.key][y.key],n[p.key][y.key]1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],a=!(arguments.length>5&&void 0!==arguments[5])||arguments[5];arguments.length>3&&void 0!==arguments[3]&&!arguments[3]?(n0&&e.splice(0,t)):e=e.slice(t,n);for(var i=0,o=e.length-1;o>=0;o--){var s=e[o];a?isFinite(s)||(e[o]=-1/0,i++):e.splice(o,1)}r&&e.sort((function(e,t){return e-t}));var l=e.length,u=Math.floor(l/2);return l%2!=0?e[u+1+i]:(e[u-1+i]+e[u+i])/2}(e):"mean"===t?function(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=0,a=0,i=t;i1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=1/0,a=t;a1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:e.length,r=-1/0,a=t;ao&&(i=l,o=t[a*e+l])}i>0&&r.push(i)}for(var u=0;u=P?(S=P,P=D,B=_):D>S&&(S=D);for(var A=0;A0?1:0;k[E%u.minIterations*t+z]=O,L+=O}if(L>0&&(E>=u.minIterations-1||E==u.maxIterations-1)){for(var V=0,F=0;F0&&r.push(a);return r}(t,i,o),q=function(e,t,n){for(var r=_r(e,t,n),a=0;al&&(s=u,l=c)}n[a]=i[s]}return _r(e,t,n)}(t,r,X),Y={},W=0;W1||o>1)&&(u=!0),c[t]=[],e.outgoers().forEach((function(e){e.isEdge()&&c[t].push(e.id())}))}else d[t]=[void 0,e.target().id()]})):l.forEach((function(e){var t=e.id();e.isNode()?(e.degree(!0)%2&&(n?r?u=!0:r=t:n=t),c[t]=[],e.connectedEdges().forEach((function(e){return c[t].push(e.id())}))):d[t]=[e.source().id(),e.target().id()]}));var h={found:!1,trail:void 0};if(u)return h;if(r&&n)if(s){if(a&&r!=a)return h;a=r}else{if(a&&r!=a&&n!=a)return h;a||(a=r)}else a||(a=l[0].id());var f=function(e){for(var t,n,r,a=e,i=[e];c[a].length;)t=c[a].shift(),n=d[t][0],a!=(r=d[t][1])?(c[r]=c[r].filter((function(e){return e!=t})),a=r):s||a==n||(c[n]=c[n].filter((function(e){return e!=t})),a=n),i.unshift(t),i.unshift(a);return i},p=[],v=[];for(v=f(a);1!=v.length;)0==c[v[0]].length?(p.unshift(l.getElementById(v.shift())),p.unshift(l.getElementById(v.shift()))):v=f(v.shift()).concat(v);for(var g in p.unshift(l.getElementById(v.shift())),c)if(c[g].length)return h;return h.found=!0,h.trail=this.spawn(p,!0),h}},Nr=function(){var e=this,t={},n=0,r=0,a=[],i=[],o={},s=function(l,u,c){l===c&&(r+=1),t[u]={id:n,low:n++,cutVertex:!1};var d,h,f,p,v=e.getElementById(u).connectedEdges().intersection(e);0===v.size()?a.push(e.spawn(e.getElementById(u))):v.forEach((function(n){d=n.source().id(),h=n.target().id(),(f=d===u?h:d)!==c&&(p=n.id(),o[p]||(o[p]=!0,i.push({x:u,y:f,edge:n})),f in t?t[u].low=Math.min(t[u].low,t[f].id):(s(l,f,u),t[u].low=Math.min(t[u].low,t[f].low),t[u].id<=t[f].low&&(t[u].cutVertex=!0,function(n,r){for(var o=i.length-1,s=[],l=e.spawn();i[o].x!=n||i[o].y!=r;)s.push(i.pop().edge),o--;s.push(i.pop().edge),s.forEach((function(n){var r=n.connectedNodes().intersection(e);l.merge(n),r.forEach((function(n){var r=n.id(),a=n.connectedEdges().intersection(e);l.merge(n),t[r].cutVertex?l.merge(a.filter((function(e){return e.isLoop()}))):l.merge(a)}))})),a.push(l)}(u,f))))}))};e.forEach((function(e){if(e.isNode()){var n=e.id();n in t||(r=0,s(n,n),t[n].cutVertex=r>1)}}));var l=Object.keys(t).filter((function(e){return t[e].cutVertex})).map((function(t){return e.getElementById(t)}));return{cut:e.spawn(l),components:a}},Lr=function(){var e=this,t={},n=0,r=[],a=[],i=e.spawn(e),o=function(s){if(a.push(s),t[s]={index:n,low:n++,explored:!1},e.getElementById(s).connectedEdges().intersection(e).forEach((function(e){var n=e.target().id();n!==s&&(n in t||o(n),t[n].explored||(t[s].low=Math.min(t[s].low,t[n].low)))})),t[s].index===t[s].low){for(var l=e.spawn();;){var u=a.pop();if(l.merge(e.getElementById(u)),t[u].low=t[s].index,t[u].explored=!0,u===s)break}var c=l.edgesWith(l),d=l.merge(c);r.push(d),i=i.difference(d)}};return e.forEach((function(e){if(e.isNode()){var n=e.id();n in t||o(n)}})),{cut:i,components:r}},zr={};[mt,Bt,Dt,At,Rt,Nt,Vt,Mn,In,Ln,On,Kn,mr,Pr,Mr,Ir,{hopcroftTarjanBiconnected:Nr,htbc:Nr,htb:Nr,hopcroftTarjanBiconnectedComponents:Nr},{tarjanStronglyConnected:Lr,tsc:Lr,tscc:Lr,tarjanStronglyConnectedComponents:Lr}].forEach((function(e){ge(zr,e)})); +/*! + Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable + Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) + Licensed under The MIT License (http://opensource.org/licenses/MIT) + */ +var Or=function(e){if(!(this instanceof Or))return new Or(e);this.id="Thenable/1.0.7",this.state=0,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},"function"==typeof e&&e.call(this,this.fulfill.bind(this),this.reject.bind(this))};Or.prototype={fulfill:function(e){return Vr(this,1,"fulfillValue",e)},reject:function(e){return Vr(this,2,"rejectReason",e)},then:function(e,t){var n=this,r=new Or;return n.onFulfilled.push(Xr(e,r,"fulfill")),n.onRejected.push(Xr(t,r,"reject")),Fr(n),r.proxy}};var Vr=function(e,t,n,r){return 0===e.state&&(e.state=t,e[n]=r,Fr(e)),e},Fr=function(e){1===e.state?jr(e,"onFulfilled",e.fulfillValue):2===e.state&&jr(e,"onRejected",e.rejectReason)},jr=function(e,t,n){if(0!==e[t].length){var r=e[t];e[t]=[];var a=function(){for(var e=0;e0:void 0}},clearQueue:function(){return function(){var e=this,t=void 0!==e.length?e:[e];if(!(this._private.cy||this).styleEnabled())return this;for(var n=0;n-1}}(),a=function(){if(Oa)return za;Oa=1;var e=Ri();return za=function(t,n){var r=this.__data__,a=e(r,t);return a<0?(++this.size,r.push([t,n])):r[a][1]=n,this},za}();function i(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&t%1==0&&t0&&this.spawn(r).updateStyle().emit("class"),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return null!=t&&t._private.classes.has(e)},toggleClass:function(e,t){H(e)||(e=e.match(/\S+/g)||[]);for(var n=this,r=void 0===t,a=[],i=0,o=n.length;i0&&this.spawn(a).updateStyle().emit("class"),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var n=this;if(null==t)t=250;else if(0===t)return n;return n.addClass(e),setTimeout((function(){n.removeClass(e)}),t),n}};bo.className=bo.classNames=bo.classes;var xo={metaChar:"[\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:"\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'",number:ce,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$",group:"node|edge|\\*",directedEdge:"\\s+->\\s+",undirectedEdge:"\\s+<->\\s+"};xo.variable="(?:[\\w-.]|(?:\\\\"+xo.metaChar+"))+",xo.className="(?:[\\w-]|(?:\\\\"+xo.metaChar+"))+",xo.value=xo.string+"|"+xo.number,xo.id=xo.variable,function(){var e,t,n;for(e=xo.comparatorOp.split("|"),n=0;n=0||"="!==t&&(xo.comparatorOp+="|\\!"+t)}();var wo=0,Eo=1,ko=2,To=3,Co=4,Po=5,So=6,Bo=7,Do=8,_o=9,Ao=10,Mo=11,Ro=12,Io=13,No=14,Lo=15,zo=16,Oo=17,Vo=18,Fo=19,jo=20,Xo=[{selector:":selected",matches:function(e){return e.selected()}},{selector:":unselected",matches:function(e){return!e.selected()}},{selector:":selectable",matches:function(e){return e.selectable()}},{selector:":unselectable",matches:function(e){return!e.selectable()}},{selector:":locked",matches:function(e){return e.locked()}},{selector:":unlocked",matches:function(e){return!e.locked()}},{selector:":visible",matches:function(e){return e.visible()}},{selector:":hidden",matches:function(e){return!e.visible()}},{selector:":transparent",matches:function(e){return e.transparent()}},{selector:":grabbed",matches:function(e){return e.grabbed()}},{selector:":free",matches:function(e){return!e.grabbed()}},{selector:":removed",matches:function(e){return e.removed()}},{selector:":inside",matches:function(e){return!e.removed()}},{selector:":grabbable",matches:function(e){return e.grabbable()}},{selector:":ungrabbable",matches:function(e){return!e.grabbable()}},{selector:":animated",matches:function(e){return e.animated()}},{selector:":unanimated",matches:function(e){return!e.animated()}},{selector:":parent",matches:function(e){return e.isParent()}},{selector:":childless",matches:function(e){return e.isChildless()}},{selector:":child",matches:function(e){return e.isChild()}},{selector:":orphan",matches:function(e){return e.isOrphan()}},{selector:":nonorphan",matches:function(e){return e.isChild()}},{selector:":compound",matches:function(e){return e.isNode()?e.isParent():e.source().isParent()||e.target().isParent()}},{selector:":loop",matches:function(e){return e.isLoop()}},{selector:":simple",matches:function(e){return e.isSimple()}},{selector:":active",matches:function(e){return e.active()}},{selector:":inactive",matches:function(e){return!e.active()}},{selector:":backgrounding",matches:function(e){return e.backgrounding()}},{selector:":nonbackgrounding",matches:function(e){return!e.backgrounding()}}].sort((function(e,t){return function(e,t){return-1*ve(e,t)}(e.selector,t.selector)})),qo=function(){for(var e,t={},n=0;n0&&u.edgeCount>0)return rt("The selector `"+e+"` is invalid because it uses both a compound selector and an edge selector"),!1;if(u.edgeCount>1)return rt("The selector `"+e+"` is invalid because it uses multiple edge selectors"),!1;1===u.edgeCount&&rt("The selector `"+e+"` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.")}return!0},toString:function(){if(null!=this.toStringCache)return this.toStringCache;for(var e=function(e){return null==e?"":e},t=function(t){return W(t)?'"'+t+'"':e(t)},n=function(e){return" "+e+" "},r=function(r,i){var o=r.type,s=r.value;switch(o){case wo:var l=e(s);return l.substring(0,l.length-1);case To:var u=r.field,c=r.operator;return"["+u+n(e(c))+t(s)+"]";case Po:var d=r.operator,h=r.field;return"["+e(d)+h+"]";case Co:return"["+r.field+"]";case So:var f=r.operator;return"[["+r.field+n(e(f))+t(s)+"]]";case Bo:return s;case Do:return"#"+s;case _o:return"."+s;case Oo:case Lo:return a(r.parent,i)+n(">")+a(r.child,i);case Vo:case zo:return a(r.ancestor,i)+" "+a(r.descendant,i);case Fo:var p=a(r.left,i),v=a(r.subject,i),g=a(r.right,i);return p+(p.length>0?" ":"")+v+g;case jo:return""}},a=function(e,t){return e.checks.reduce((function(n,a,i){return n+(t===e&&0===i?"$":"")+r(a,t)}),"")},i="",o=0;o1&&o=0&&(t=t.replace("!",""),c=!0),t.indexOf("@")>=0&&(t=t.replace("@",""),u=!0),(o||l||u)&&(a=o||s?""+e:"",i=""+n),u&&(e=a=a.toLowerCase(),n=i=i.toLowerCase()),t){case"*=":r=a.indexOf(i)>=0;break;case"$=":r=a.indexOf(i,a.length-i.length)>=0;break;case"^=":r=0===a.indexOf(i);break;case"=":r=e===n;break;case">":d=!0,r=e>n;break;case">=":d=!0,r=e>=n;break;case"<":d=!0,r=e0;){var u=a.shift();t(u),i.add(u.id()),o&&r(a,i,u)}return e}function us(e,t,n){if(n.isParent())for(var r=n._private.children,a=0;a1&&void 0!==arguments[1])||arguments[1],us)},ss.forEachUp=function(e){return ls(this,e,!(arguments.length>1&&void 0!==arguments[1])||arguments[1],cs)},ss.forEachUpAndDown=function(e){return ls(this,e,!(arguments.length>1&&void 0!==arguments[1])||arguments[1],ds)},ss.ancestors=ss.parents,(as=is={data:yo.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:yo.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:yo.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:yo.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),rscratch:yo.data({field:"rscratch",allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:yo.removeData({field:"rscratch",triggerEvent:!1}),id:function(){var e=this[0];if(e)return e._private.data.id}}).attr=as.data,as.removeAttr=as.removeData;var hs,fs,ps=is,vs={};function gs(e){return function(t){var n=this;if(void 0===t&&(t=!0),0!==n.length&&n.isNode()&&!n.removed()){for(var r=0,a=n[0],i=a._private.edges,o=0;ot})),minIndegree:ys("indegree",(function(e,t){return et})),minOutdegree:ys("outdegree",(function(e,t){return et}))}),ge(vs,{totalDegree:function(e){for(var t=0,n=this.nodes(),r=0;r0,c=u;u&&(l=l[0]);var d=c?l.position():{x:0,y:0};return a={x:s.x-d.x,y:s.y-d.y},void 0===e?a:a[e]}for(var h=0;h0,g=v;v&&(p=p[0]);var y=g?p.position():{x:0,y:0};void 0!==t?f.position(e,t+y[e]):void 0!==a&&f.position({x:a.x+y.x,y:a.y+y.y})}}else if(!i)return;return this}},hs.modelPosition=hs.point=hs.position,hs.modelPositions=hs.points=hs.positions,hs.renderedPoint=hs.renderedPosition,hs.relativePoint=hs.relativePosition;var xs,ws,Es=fs;xs=ws={},ws.renderedBoundingBox=function(e){var t=this.boundingBox(e),n=this.cy(),r=n.zoom(),a=n.pan(),i=t.x1*r+a.x,o=t.x2*r+a.x,s=t.y1*r+a.y,l=t.y2*r+a.y;return{x1:i,x2:o,y1:s,y2:l,w:o-i,h:l-s}},ws.dirtyCompoundBoundsCache=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.cy();return t.styleEnabled()&&t.hasCompoundNodes()?(this.forEachUp((function(t){if(t.isParent()){var n=t._private;n.compoundBoundsClean=!1,n.bbCache=null,e||t.emitAndNotify("bounds")}})),this):this},ws.updateCompoundBounds=function(){var e=arguments.length>0&&void 0!==arguments[0]&&arguments[0],t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes())return this;if(!e&&t.batching())return this;function n(e){if(e.isParent()){var t=e._private,n=e.children(),r="include"===e.pstyle("compound-sizing-wrt-labels").value,a={width:{val:e.pstyle("min-width").pfValue,left:e.pstyle("min-width-bias-left"),right:e.pstyle("min-width-bias-right")},height:{val:e.pstyle("min-height").pfValue,top:e.pstyle("min-height-bias-top"),bottom:e.pstyle("min-height-bias-bottom")}},i=n.boundingBox({includeLabels:r,includeOverlays:!1,useCache:!1}),o=t.position;0!==i.w&&0!==i.h||((i={w:e.pstyle("width").pfValue,h:e.pstyle("height").pfValue}).x1=o.x-i.w/2,i.x2=o.x+i.w/2,i.y1=o.y-i.h/2,i.y2=o.y+i.h/2);var s=a.width.left.value;"px"===a.width.left.units&&a.width.val>0&&(s=100*s/a.width.val);var l=a.width.right.value;"px"===a.width.right.units&&a.width.val>0&&(l=100*l/a.width.val);var u=a.height.top.value;"px"===a.height.top.units&&a.height.val>0&&(u=100*u/a.height.val);var c=a.height.bottom.value;"px"===a.height.bottom.units&&a.height.val>0&&(c=100*c/a.height.val);var d=y(a.width.val-i.w,s,l),h=d.biasDiff,f=d.biasComplementDiff,p=y(a.height.val-i.h,u,c),v=p.biasDiff,g=p.biasComplementDiff;t.autoPadding=function(e,t,n,r){if("%"!==n.units)return"px"===n.units?n.pfValue:0;switch(r){case"width":return e>0?n.pfValue*e:0;case"height":return t>0?n.pfValue*t:0;case"average":return e>0&&t>0?n.pfValue*(e+t)/2:0;case"min":return e>0&&t>0?e>t?n.pfValue*t:n.pfValue*e:0;case"max":return e>0&&t>0?e>t?n.pfValue*e:n.pfValue*t:0;default:return 0}}(i.w,i.h,e.pstyle("padding"),e.pstyle("padding-relative-to").value),t.autoWidth=Math.max(i.w,a.width.val),o.x=(-h+i.x1+i.x2+f)/2,t.autoHeight=Math.max(i.h,a.height.val),o.y=(-v+i.y1+i.y2+g)/2}function y(e,t,n){var r=0,a=0,i=t+n;return e>0&&i>0&&(r=t/i*e,a=n/i*e),{biasDiff:r,biasComplementDiff:a}}}for(var r=0;re.x2?r:e.x2,e.y1=ne.y2?a:e.y2,e.w=e.x2-e.x1,e.h=e.y2-e.y1)},Cs=function(e,t){return null==t?e:Ts(e,t.x1,t.y1,t.x2,t.y2)},Ps=function(e,t,n){return dt(e,t,n)},Ss=function(e,t,n){if(!t.cy().headless()){var r,a,i=t._private,o=i.rstyle,s=o.arrowWidth/2;if("none"!==t.pstyle(n+"-arrow-shape").value){"source"===n?(r=o.srcX,a=o.srcY):"target"===n?(r=o.tgtX,a=o.tgtY):(r=o.midX,a=o.midY);var l=i.arrowBounds=i.arrowBounds||{},u=l[n]=l[n]||{};u.x1=r-s,u.y1=a-s,u.x2=r+s,u.y2=a+s,u.w=u.x2-u.x1,u.h=u.y2-u.y1,en(u,1),Ts(e,u.x1,u.y1,u.x2,u.y2)}}},Bs=function(e,t,n){if(!t.cy().headless()){var r;r=n?n+"-":"";var a=t._private,i=a.rstyle;if(t.pstyle(r+"label").strValue){var o,s,l,u,c=t.pstyle("text-halign"),d=t.pstyle("text-valign"),h=Ps(i,"labelWidth",n),f=Ps(i,"labelHeight",n),p=Ps(i,"labelX",n),v=Ps(i,"labelY",n),g=t.pstyle(r+"text-margin-x").pfValue,y=t.pstyle(r+"text-margin-y").pfValue,m=t.isEdge(),b=t.pstyle(r+"text-rotation"),x=t.pstyle("text-outline-width").pfValue,w=t.pstyle("text-border-width").pfValue/2,E=t.pstyle("text-background-padding").pfValue,k=f,T=h,C=T/2,P=k/2;if(m)o=p-C,s=p+C,l=v-P,u=v+P;else{switch(c.value){case"left":o=p-T,s=p;break;case"center":o=p-C,s=p+C;break;case"right":o=p,s=p+T}switch(d.value){case"top":l=v-k,u=v;break;case"center":l=v-P,u=v+P;break;case"bottom":l=v,u=v+k}}var S=g-Math.max(x,w)-E-2,B=g+Math.max(x,w)+E+2,D=y-Math.max(x,w)-E-2,_=y+Math.max(x,w)+E+2;o+=S,s+=B,l+=D,u+=_;var A=n||"main",M=a.labelBounds,R=M[A]=M[A]||{};R.x1=o,R.y1=l,R.x2=s,R.y2=u,R.w=s-o,R.h=u-l,R.leftPad=S,R.rightPad=B,R.topPad=D,R.botPad=_;var I=m&&"autorotate"===b.strValue,N=null!=b.pfValue&&0!==b.pfValue;if(I||N){var L=I?Ps(a.rstyle,"labelAngle",n):b.pfValue,z=Math.cos(L),O=Math.sin(L),V=(o+s)/2,F=(l+u)/2;if(!m){switch(c.value){case"left":V=s;break;case"right":V=o}switch(d.value){case"top":F=u;break;case"bottom":F=l}}var j=function(e,t){return{x:(e-=V)*z-(t-=F)*O+V,y:e*O+t*z+F}},X=j(o,l),q=j(o,u),Y=j(s,l),W=j(s,u);o=Math.min(X.x,q.x,Y.x,W.x),s=Math.max(X.x,q.x,Y.x,W.x),l=Math.min(X.y,q.y,Y.y,W.y),u=Math.max(X.y,q.y,Y.y,W.y)}var U=A+"Rot",H=M[U]=M[U]||{};H.x1=o,H.y1=l,H.x2=s,H.y2=u,H.w=s-o,H.h=u-l,Ts(e,o,l,s,u),Ts(a.labelBounds.all,o,l,s,u)}return e}},Ds=function(e,t){if(!t.cy().headless()){var n=t.pstyle("outline-opacity").value,r=t.pstyle("outline-width").value+t.pstyle("outline-offset").value;_s(e,t,n,r,"outside",r/2)}},_s=function(e,t,n,r,a,i){if(!(0===n||r<=0||"inside"===a)){var o=t.cy(),s=t.pstyle("shape").value,l=o.renderer().nodeShapes[s],u=t.position(),c=u.x,d=u.y,h=t.width(),f=t.height();if(l.hasMiterBounds){"center"===a&&(r/=2);var p=l.miterBounds(c,d,h,f,r);Cs(e,p)}else null!=i&&i>0&&tn(e,[i,i,i,i])}},As=function(e,t){var n,r,a,i,o,s,l,u=e._private.cy,c=u.styleEnabled(),d=u.headless(),h=Qt(),f=e._private,p=e.isNode(),v=e.isEdge(),g=f.rstyle,y=p&&c?e.pstyle("bounds-expansion").pfValue:[0],m=function(e){return"none"!==e.pstyle("display").value},b=!c||m(e)&&(!v||m(e.source())&&m(e.target()));if(b){var x=0;c&&t.includeOverlays&&0!==e.pstyle("overlay-opacity").value&&(x=e.pstyle("overlay-padding").value);var w=0;c&&t.includeUnderlays&&0!==e.pstyle("underlay-opacity").value&&(w=e.pstyle("underlay-padding").value);var E=Math.max(x,w),k=0;if(c&&(k=e.pstyle("width").pfValue/2),p&&t.includeNodes){var T=e.position();o=T.x,s=T.y;var C=e.outerWidth()/2,P=e.outerHeight()/2;Ts(h,n=o-C,a=s-P,r=o+C,i=s+P),c&&Ds(h,e),c&&t.includeOutlines&&!d&&Ds(h,e),c&&function(e,t){if(!t.cy().headless()){var n=t.pstyle("border-opacity").value,r=t.pstyle("border-width").pfValue,a=t.pstyle("border-position").value;_s(e,t,n,r,a)}}(h,e)}else if(v&&t.includeEdges)if(c&&!d){var S=e.pstyle("curve-style").strValue;if(n=Math.min(g.srcX,g.midX,g.tgtX),r=Math.max(g.srcX,g.midX,g.tgtX),a=Math.min(g.srcY,g.midY,g.tgtY),i=Math.max(g.srcY,g.midY,g.tgtY),Ts(h,n-=k,a-=k,r+=k,i+=k),"haystack"===S){var B=g.haystackPts;if(B&&2===B.length){if(n=B[0].x,a=B[0].y,n>(r=B[1].x)){var D=n;n=r,r=D}if(a>(i=B[1].y)){var _=a;a=i,i=_}Ts(h,n-k,a-k,r+k,i+k)}}else if("bezier"===S||"unbundled-bezier"===S||ue(S,"segments")||ue(S,"taxi")){var A;switch(S){case"bezier":case"unbundled-bezier":A=g.bezierPts;break;case"segments":case"taxi":case"round-segments":case"round-taxi":A=g.linePts}if(null!=A)for(var M=0;M(r=N.x)){var L=n;n=r,r=L}if((a=I.y)>(i=N.y)){var z=a;a=i,i=z}Ts(h,n-=k,a-=k,r+=k,i+=k)}if(c&&t.includeEdges&&v&&(Ss(h,e,"mid-source"),Ss(h,e,"mid-target"),Ss(h,e,"source"),Ss(h,e,"target")),c)if("yes"===e.pstyle("ghost").value){var O=e.pstyle("ghost-offset-x").pfValue,V=e.pstyle("ghost-offset-y").pfValue;Ts(h,h.x1+O,h.y1+V,h.x2+O,h.y2+V)}var F=f.bodyBounds=f.bodyBounds||{};nn(F,h),tn(F,y),en(F,1),c&&(n=h.x1,r=h.x2,a=h.y1,i=h.y2,Ts(h,n-E,a-E,r+E,i+E));var j=f.overlayBounds=f.overlayBounds||{};nn(j,h),tn(j,y),en(j,1);var X=f.labelBounds=f.labelBounds||{};null!=X.all?((l=X.all).x1=1/0,l.y1=1/0,l.x2=-1/0,l.y2=-1/0,l.w=0,l.h=0):X.all=Qt(),c&&t.includeLabels&&(t.includeMainLabels&&Bs(h,e,null),v&&(t.includeSourceLabels&&Bs(h,e,"source"),t.includeTargetLabels&&Bs(h,e,"target")))}return h.x1=ks(h.x1),h.y1=ks(h.y1),h.x2=ks(h.x2),h.y2=ks(h.y2),h.w=ks(h.x2-h.x1),h.h=ks(h.y2-h.y1),h.w>0&&h.h>0&&b&&(tn(h,y),en(h,1)),h},Ms=function(e){var t=0,n=function(e){return(e?1:0)<0&&void 0!==arguments[0]?arguments[0]:Qs,t=arguments.length>1?arguments[1]:void 0,n=0;n<$s.length;n++){var r=$s[n];this[r]=e[r]||Zs[r]}this.context=t||this.context,this.listeners=[],this.emitting=0}var el=Js.prototype,tl=function(e,t,n,r,a,i,o){U(r)&&(a=r,r=null),o&&(i=null==i?o:ge({},i,o));for(var s=H(n)?n:n.split(/\s+/),l=0;l=0;s--)o(s);return this},el.removeAllListeners=function(){return this.removeListener("*")},el.emit=el.trigger=function(e,t,n){var r=this.listeners,a=r.length;return this.emitting++,H(t)||(t=[t]),rl(this,(function(e,i){null!=n&&(r=[{event:i.event,type:i.type,namespace:i.namespace,callback:n}],a=r.length);for(var o=function(){var n=r[s];if(n.type===i.type&&(!n.namespace||n.namespace===i.namespace||".*"===n.namespace)&&e.eventMatches(e.context,n,i)){var a=[i];null!=t&&function(e,t){for(var n=0;n1&&!r){var a=this.length-1,i=this[a],o=i._private.data.id;this[a]=void 0,this[e]=i,n.set(o,{ele:i,index:e})}return this.length--,this},unmergeOne:function(e){e=e[0];var t=this._private,n=e._private.data.id,r=t.map.get(n);if(!r)return this;var a=r.index;return this.unmergeAt(a),this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(e&&W(e)){var n=e;e=t.mutableElements().filter(n)}for(var r=0;r=0;t--){e(this[t])&&this.unmergeAt(t)}return this},map:function(e,t){for(var n=[],r=this,a=0;ar&&(r=s,n=o)}return{value:r,ele:n}},min:function(e,t){for(var n,r=1/0,a=this,i=0;i=0&&a1&&void 0!==arguments[1])||arguments[1],n=this[0],r=n.cy();if(r.styleEnabled()&&n){n._private.styleDirty&&(n._private.styleDirty=!1,r.style().apply(n));var a=n._private.style[e];return null!=a?a:t?r.style().getDefaultProperty(e):null}},numericStyle:function(e){var t=this[0];if(t.cy().styleEnabled()&&t){var n=t.pstyle(e);return void 0!==n.pfValue?n.pfValue:n.value}},numericStyleUnits:function(e){var t=this[0];if(t.cy().styleEnabled())return t?t.pstyle(e).units:void 0},renderedStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=this[0];return n?t.style().getRenderedStyle(n,e):void 0},style:function(e,t){var n=this.cy();if(!n.styleEnabled())return this;var r=!1,a=n.style();if(K(e)){var i=e;a.applyBypass(this,i,r),this.emitAndNotify("style")}else if(W(e)){if(void 0===t){var o=this[0];return o?a.getStylePropertyValue(o,e):void 0}a.applyBypass(this,e,t,r),this.emitAndNotify("style")}else if(void 0===e){var s=this[0];return s?a.getRawStyle(s):void 0}return this},removeStyle:function(e){var t=this.cy();if(!t.styleEnabled())return this;var n=!1,r=t.style(),a=this;if(void 0===e)for(var i=0;i0&&t.push(c[0]),t.push(s[0])}return this.spawn(t,!0).filter(e)}),"neighborhood"),closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),Bl.neighbourhood=Bl.neighborhood,Bl.closedNeighbourhood=Bl.closedNeighborhood,Bl.openNeighbourhood=Bl.openNeighborhood,ge(Bl,{source:os((function(e){var t,n=this[0];return n&&(t=n._private.source||n.cy().collection()),t&&e?t.filter(e):t}),"source"),target:os((function(e){var t,n=this[0];return n&&(t=n._private.target||n.cy().collection()),t&&e?t.filter(e):t}),"target"),sources:Ml({attr:"source"}),targets:Ml({attr:"target"})}),ge(Bl,{edgesWith:os(Rl(),"edgesWith"),edgesTo:os(Rl({thisIsSrc:!0}),"edgesTo")}),ge(Bl,{connectedEdges:os((function(e){for(var t=[],n=0;n0);return i},component:function(){var e=this[0];return e.cy().mutableElements().components(e)[0]}}),Bl.componentsOf=Bl.components;var Nl=function(e,t){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=arguments.length>3&&void 0!==arguments[3]&&arguments[3];if(void 0!==e){var a=new ft,i=!1;if(t){if(t.length>0&&K(t[0])&&!Q(t[0])){i=!0;for(var o=[],s=new vt,l=0,u=t.length;l0&&void 0!==arguments[0])||arguments[0],r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=this,i=a.cy(),o=i._private,s=[],l=[],u=0,c=a.length;u0){for(var I=e.length===a.length?a:new Nl(i,e),N=0;N0&&void 0!==arguments[0])||arguments[0],t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],n=this,r=[],a={},i=n._private.cy;function o(e){var n=a[e.id()];t&&e.removed()||n||(a[e.id()]=!0,e.isNode()?(r.push(e),function(e){for(var t=e._private.edges,n=0;n0&&(e?k.emitAndNotify("remove"):t&&k.emit("remove"));for(var T=0;T=.001?function(t,r){for(var a=0;a<4;++a){var i=h(r,e,n);if(0===i)return r;r-=(d(r,e,n)-t)/i}return r}(t,o):0===l?o:function(t,r,a){var i,o,s=0;do{(i=d(o=r+(a-r)/2,e,n)-t)>0?a=o:r=o}while(Math.abs(i)>1e-7&&++s<10);return o}(t,r,r+a)}var p=!1;function v(){p=!0,e===t&&n===r||function(){for(var t=0;t<11;++t)s[t]=d(t*a,e,n)}()}var g=function(a){return p||v(),e===t&&n===r?a:0===a?0:1===a?1:d(f(a),t,r)};g.getControlPoints=function(){return[{x:e,y:t},{x:n,y:r}]};var y="generateBezier("+[e,t,n,r]+")";return g.toString=function(){return y},g} +/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */var Vl=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,n,r){var a={x:t.x+r.dx*n,v:t.v+r.dv*n,tension:t.tension,friction:t.friction};return{dx:a.v,dv:e(a)}}function n(n,r){var a={dx:n.v,dv:e(n)},i=t(n,.5*r,a),o=t(n,.5*r,i),s=t(n,r,o),l=1/6*(a.dx+2*(i.dx+o.dx)+s.dx),u=1/6*(a.dv+2*(i.dv+o.dv)+s.dv);return n.x=n.x+l*r,n.v=n.v+u*r,n}return function e(t,r,a){var i,o,s,l={x:-1,v:0,tension:null,friction:null},u=[0],c=0,d=1e-4;for(t=parseFloat(t)||500,r=parseFloat(r)||20,a=a||null,l.tension=t,l.friction=r,o=(i=null!==a)?(c=e(t,r))/a*.016:.016;s=n(s||l,o),u.push(1+s.x),c+=16,Math.abs(s.x)>d&&Math.abs(s.v)>d;);return i?function(e){return u[e*(u.length-1)|0]}:c}}(),Fl=function(e,t,n,r){var a=Ol(e,t,n,r);return function(e,t,n){return e+(t-e)*a(n)}},jl={linear:function(e,t,n){return e+(t-e)*n},ease:Fl(.25,.1,.25,1),"ease-in":Fl(.42,0,1,1),"ease-out":Fl(0,0,.58,1),"ease-in-out":Fl(.42,0,.58,1),"ease-in-sine":Fl(.47,0,.745,.715),"ease-out-sine":Fl(.39,.575,.565,1),"ease-in-out-sine":Fl(.445,.05,.55,.95),"ease-in-quad":Fl(.55,.085,.68,.53),"ease-out-quad":Fl(.25,.46,.45,.94),"ease-in-out-quad":Fl(.455,.03,.515,.955),"ease-in-cubic":Fl(.55,.055,.675,.19),"ease-out-cubic":Fl(.215,.61,.355,1),"ease-in-out-cubic":Fl(.645,.045,.355,1),"ease-in-quart":Fl(.895,.03,.685,.22),"ease-out-quart":Fl(.165,.84,.44,1),"ease-in-out-quart":Fl(.77,0,.175,1),"ease-in-quint":Fl(.755,.05,.855,.06),"ease-out-quint":Fl(.23,1,.32,1),"ease-in-out-quint":Fl(.86,0,.07,1),"ease-in-expo":Fl(.95,.05,.795,.035),"ease-out-expo":Fl(.19,1,.22,1),"ease-in-out-expo":Fl(1,0,0,1),"ease-in-circ":Fl(.6,.04,.98,.335),"ease-out-circ":Fl(.075,.82,.165,1),"ease-in-out-circ":Fl(.785,.135,.15,.86),spring:function(e,t,n){if(0===n)return jl.linear;var r=Vl(e,t,n);return function(e,t,n){return e+(t-e)*r(n)}},"cubic-bezier":Fl};function Xl(e,t,n,r,a){if(1===r)return n;if(t===n)return n;var i=a(t,n,r);return null==e||((e.roundValue||e.color)&&(i=Math.round(i)),void 0!==e.min&&(i=Math.max(i,e.min)),void 0!==e.max&&(i=Math.min(i,e.max))),i}function ql(e,t){return null!=e.pfValue||null!=e.value?null==e.pfValue||null!=t&&"%"===t.type.units?e.value:e.pfValue:e}function Yl(e,t,n,r,a){var i=null!=a?a.type:null;n<0?n=0:n>1&&(n=1);var o=ql(e,a),s=ql(t,a);if(G(o)&&G(s))return Xl(i,o,s,n,r);if(H(o)&&H(s)){for(var l=[],u=0;u0?("spring"===d&&h.push(o.duration),o.easingImpl=jl[d].apply(null,h)):o.easingImpl=jl[d]}var f,p=o.easingImpl;if(f=0===o.duration?1:(n-l)/o.duration,o.applying&&(f=o.progress),f<0?f=0:f>1&&(f=1),null==o.delay){var v=o.startPosition,g=o.position;if(g&&a&&!e.locked()){var y={};Ul(v.x,g.x)&&(y.x=Yl(v.x,g.x,f,p)),Ul(v.y,g.y)&&(y.y=Yl(v.y,g.y,f,p)),e.position(y)}var m=o.startPan,b=o.pan,x=i.pan,w=null!=b&&r;w&&(Ul(m.x,b.x)&&(x.x=Yl(m.x,b.x,f,p)),Ul(m.y,b.y)&&(x.y=Yl(m.y,b.y,f,p)),e.emit("pan"));var E=o.startZoom,k=o.zoom,T=null!=k&&r;T&&(Ul(E,k)&&(i.zoom=$t(i.minZoom,Yl(E,k,f,p),i.maxZoom)),e.emit("zoom")),(w||T)&&e.emit("viewport");var C=o.style;if(C&&C.length>0&&a){for(var P=0;P=0;t--){(0,e[t])()}e.splice(0,e.length)},c=i.length-1;c>=0;c--){var d=i[c],h=d._private;h.stopped?(i.splice(c,1),h.hooked=!1,h.playing=!1,h.started=!1,u(h.frames)):(h.playing||h.applying)&&(h.playing&&h.applying&&(h.applying=!1),h.started||Hl(0,d,e),Wl(t,d,e,n),h.applying&&(h.applying=!1),u(h.frames),null!=h.step&&h.step(e),d.completed()&&(i.splice(c,1),h.hooked=!1,h.playing=!1,h.started=!1,u(h.completes)),s=!0)}return n||0!==i.length||0!==o.length||r.push(t),s}for(var i=!1,o=0;o0?t.notify("draw",n):t.notify("draw")),n.unmerge(r),t.emit("step")}var Gl={animate:yo.animate(),animation:yo.animation(),animated:yo.animated(),clearQueue:yo.clearQueue(),delay:yo.delay(),delayAnimation:yo.delayAnimation(),stop:yo.stop(),addToAnimationPool:function(e){this.styleEnabled()&&this._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){var e=this;if(e._private.animationsRunning=!0,e.styleEnabled()){var t=e.renderer();t&&t.beforeRender?t.beforeRender((function(t,n){Kl(n,e)}),t.beforeRenderPriorities.animations):function t(){e._private.animationsRunning&&Ie((function(n){Kl(n,e),t()}))}()}}},Zl={qualifierCompare:function(e,t){return null==e||null==t?null==e&&null==t:e.sameText(t)},eventMatches:function(e,t,n){var r=t.qualifier;return null==r||e!==n.target&&Q(n.target)&&r.matches(n.target)},addEventFields:function(e,t){t.cy=e,t.target=e},callbackContext:function(e,t,n){return null!=t.qualifier?n.target:e}},$l=function(e){return W(e)?new ts(e):e},Ql={createEmitter:function(){var e=this._private;return e.emitter||(e.emitter=new Js(Zl,this)),this},emitter:function(){return this._private.emitter},on:function(e,t,n){return this.emitter().on(e,$l(t),n),this},removeListener:function(e,t,n){return this.emitter().removeListener(e,$l(t),n),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},one:function(e,t,n){return this.emitter().one(e,$l(t),n),this},once:function(e,t,n){return this.emitter().one(e,$l(t),n),this},emit:function(e,t){return this.emitter().emit(e,t),this},emitAndNotify:function(e,t){return this.emit(e),this.notify(e,t),this}};yo.eventAliasesOn(Ql);var Jl={png:function(e){return e=e||{},this._private.renderer.png(e)},jpg:function(e){var t=this._private.renderer;return(e=e||{}).bg=e.bg||"#fff",t.jpg(e)}};Jl.jpeg=Jl.jpg;var eu={layout:function(e){var t=this;if(null!=e)if(null!=e.name){var n=e.name,r=t.extension("layout",n);if(null!=r){var a;a=W(e.eles)?t.$(e.eles):null!=e.eles?e.eles:t.$();var i=new r(ge({},e,{cy:t,eles:a}));return i}tt("No such layout `"+n+"` found. Did you forget to import it and `cytoscape.use()` it?")}else tt("A `name` must be specified to make a layout");else tt("Layout options must be specified to make a layout")}};eu.createLayout=eu.makeLayout=eu.layout;var tu={notify:function(e,t){var n=this._private;if(this.batching()){n.batchNotifications=n.batchNotifications||{};var r=n.batchNotifications[e]=n.batchNotifications[e]||this.collection();null!=t&&r.merge(t)}else if(n.notificationsEnabled){var a=this.renderer();!this.destroyed()&&a&&a.notify(e,t)}},notifications:function(e){var t=this._private;return void 0===e?t.notificationsEnabled:(t.notificationsEnabled=!!e,this)},noNotifications:function(e){this.notifications(!1),e(),this.notifications(!0)},batching:function(){return this._private.batchCount>0},startBatch:function(){var e=this._private;return null==e.batchCount&&(e.batchCount=0),0===e.batchCount&&(e.batchStyleEles=this.collection(),e.batchNotifications={}),e.batchCount++,this},endBatch:function(){var e=this._private;if(0===e.batchCount)return this;if(e.batchCount--,0===e.batchCount){e.batchStyleEles.updateStyle();var t=this.renderer();Object.keys(e.batchNotifications).forEach((function(n){var r=e.batchNotifications[n];r.empty()?t.notify(n):t.notify(n,r)}))}return this},batch:function(e){return this.startBatch(),e(),this.endBatch(),this},batchData:function(e){var t=this;return this.batch((function(){for(var n=Object.keys(e),r=0;r0;)t.removeChild(t.childNodes[0]);e._private.renderer=null,e.mutableElements().forEach((function(e){var t=e._private;t.rscratch={},t.rstyle={},t.animation.current=[],t.animation.queue=[]}))},onRender:function(e){return this.on("render",e)},offRender:function(e){return this.off("render",e)}};ru.invalidateDimensions=ru.resize;var au={collection:function(e,t){return W(e)?this.$(e):$(e)?e.collection():H(e)?(t||(t={}),new Nl(this,e,t.unique,t.removed)):new Nl(this)},nodes:function(e){var t=this.$((function(e){return e.isNode()}));return e?t.filter(e):t},edges:function(e){var t=this.$((function(e){return e.isEdge()}));return e?t.filter(e):t},$:function(e){var t=this._private.elements;return e?t.filter(e):t.spawnSelf()},mutableElements:function(){return this._private.elements}};au.elements=au.filter=au.$;var iu={},ou="t";iu.apply=function(e){for(var t=this,n=t._private.cy.collection(),r=0;r0;if(h||d&&f){var p=void 0;h&&f||h?p=u.properties:f&&(p=u.mappedProperties);for(var v=0;v1&&(g=1),s.color){var w=a.valueMin[0],E=a.valueMax[0],k=a.valueMin[1],T=a.valueMax[1],C=a.valueMin[2],P=a.valueMax[2],S=null==a.valueMin[3]?1:a.valueMin[3],B=null==a.valueMax[3]?1:a.valueMax[3],D=[Math.round(w+(E-w)*g),Math.round(k+(T-k)*g),Math.round(C+(P-C)*g),Math.round(S+(B-S)*g)];n={bypass:a.bypass,name:a.name,value:D,strValue:"rgb("+D[0]+", "+D[1]+", "+D[2]+")"}}else{if(!s.number)return!1;var _=a.valueMin+(a.valueMax-a.valueMin)*g;n=this.parse(a.name,_,a.bypass,h)}if(!n)return v(),!1;n.mapping=a,a=n;break;case o.data:for(var A=a.field.split("."),M=d.data,R=0;R0&&i>0){for(var s={},l=!1,u=0;u0?e.delayAnimation(o).play().promise().then(t):t()})).then((function(){return e.animation({style:s,duration:i,easing:e.pstyle("transition-timing-function").value,queue:!1}).play().promise()})).then((function(){n.removeBypasses(e,a),e.emitAndNotify("style"),r.transitioning=!1}))}else r.transitioning&&(this.removeBypasses(e,a),e.emitAndNotify("style"),r.transitioning=!1)},iu.checkTrigger=function(e,t,n,r,a,i){var o=this.properties[t],s=a(o);e.removed()||null!=s&&s(n,r,e)&&i(o)},iu.checkZOrderTrigger=function(e,t,n,r){var a=this;this.checkTrigger(e,t,n,r,(function(e){return e.triggersZOrder}),(function(){a._private.cy.notify("zorder",e)}))},iu.checkBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,(function(e){return e.triggersBounds}),(function(t){e.dirtyCompoundBoundsCache(),e.dirtyBoundingBoxCache()}))},iu.checkConnectedEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,(function(e){return e.triggersBoundsOfConnectedEdges}),(function(t){e.connectedEdges().forEach((function(e){e.dirtyBoundingBoxCache()}))}))},iu.checkParallelEdgesBoundsTrigger=function(e,t,n,r){this.checkTrigger(e,t,n,r,(function(e){return e.triggersBoundsOfParallelEdges}),(function(t){e.parallelEdges().forEach((function(e){e.dirtyBoundingBoxCache()}))}))},iu.checkTriggers=function(e,t,n,r){e.dirtyStyleCache(),this.checkZOrderTrigger(e,t,n,r),this.checkBoundsTrigger(e,t,n,r),this.checkConnectedEdgesBoundsTrigger(e,t,n,r),this.checkParallelEdgesBoundsTrigger(e,t,n,r)};var su={applyBypass:function(e,t,n,r){var a=[];if("*"===t||"**"===t){if(void 0!==n)for(var i=0;it.length?i.substr(t.length):""}function s(){n=n.length>r.length?n.substr(r.length):""}for(i=i.replace(/[/][*](\s|.)+?[*][/]/g,"");;){if(i.match(/^\s*$/))break;var l=i.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!l){rt("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+i);break}t=l[0];var u=l[1];if("core"!==u)if(new ts(u).invalid){rt("Skipping parsing of block: Invalid selector found in string stylesheet: "+u),o();continue}var c=l[2],d=!1;n=c;for(var h=[];;){if(n.match(/^\s*$/))break;var f=n.match(/^\s*(.+?)\s*:\s*(.+?)(?:\s*;|\s*$)/);if(!f){rt("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+c),d=!0;break}r=f[0];var p=f[1],v=f[2];if(this.properties[p])a.parse(p,v)?(h.push({name:p,val:v}),s()):(rt("Skipping property: Invalid property definition in: "+r),s());else rt("Skipping property: Invalid property name in: "+r),s()}if(d){o();break}a.selector(u);for(var g=0;g=7&&"d"===t[0]&&(u=new RegExp(s.data.regex).exec(t))){if(n)return!1;var h=s.data;return{name:e,value:u,strValue:""+t,mapped:h,field:u[1],bypass:n}}if(t.length>=10&&"m"===t[0]&&(c=new RegExp(s.mapData.regex).exec(t))){if(n)return!1;if(d.multiple)return!1;var f=s.mapData;if(!d.color&&!d.number)return!1;var p=this.parse(e,c[4]);if(!p||p.mapped)return!1;var v=this.parse(e,c[5]);if(!v||v.mapped)return!1;if(p.pfValue===v.pfValue||p.strValue===v.strValue)return rt("`"+e+": "+t+"` is not a valid mapper because the output range is zero; converting to `"+e+": "+p.strValue+"`"),this.parse(e,p.strValue);if(d.color){var g=p.value,y=v.value;if(!(g[0]!==y[0]||g[1]!==y[1]||g[2]!==y[2]||g[3]!==y[3]&&(null!=g[3]&&1!==g[3]||null!=y[3]&&1!==y[3])))return!1}return{name:e,value:c,strValue:""+t,mapped:f,field:c[1],fieldMin:parseFloat(c[2]),fieldMax:parseFloat(c[3]),valueMin:p.value,valueMax:v.value,bypass:n}}}if(d.multiple&&"multiple"!==r){var m;if(m=l?t.split(/\s+/):H(t)?t:[t],d.evenMultiple&&m.length%2!=0)return null;for(var b=[],x=[],w=[],E="",k=!1,T=0;T0?" ":"")+C.strValue}return d.validate&&!d.validate(b,x)?null:d.singleEnum&&k?1===b.length&&W(b[0])?{name:e,value:b[0],strValue:b[0],bypass:n}:null:{name:e,value:b,pfValue:w,strValue:E,bypass:n,units:x}}var P,S,B=function(){for(var r=0;rd.max||d.strictMax&&t===d.max))return null;var R={name:e,value:t,strValue:""+t+(D||""),units:D,bypass:n};return d.unitless||"px"!==D&&"em"!==D?R.pfValue=t:R.pfValue="px"!==D&&D?this.getEmSizeInPixels()*t:t,"ms"!==D&&"s"!==D||(R.pfValue="ms"===D?t:1e3*t),"deg"!==D&&"rad"!==D||(R.pfValue="rad"===D?t:(P=t,Math.PI*P/180)),"%"===D&&(R.pfValue=t/100),R}if(d.propList){var I=[],N=""+t;if("none"===N);else{for(var L=N.split(/\s*,\s*|\s+/),z=0;z0&&l>0&&!isNaN(n.w)&&!isNaN(n.h)&&n.w>0&&n.h>0)return{zoom:o=(o=(o=Math.min((s-2*t)/n.w,(l-2*t)/n.h))>this._private.maxZoom?this._private.maxZoom:o)=n.minZoom&&(n.maxZoom=t),this},minZoom:function(e){return void 0===e?this._private.minZoom:this.zoomRange({min:e})},maxZoom:function(e){return void 0===e?this._private.maxZoom:this.zoomRange({max:e})},getZoomedViewport:function(e){var t,n,r=this._private,a=r.pan,i=r.zoom,o=!1;if(r.zoomingEnabled||(o=!0),G(e)?n=e:K(e)&&(n=e.level,null!=e.position?t=Ft(e.position,i,a):null!=e.renderedPosition&&(t=e.renderedPosition),null==t||r.panningEnabled||(o=!0)),n=(n=n>r.maxZoom?r.maxZoom:n)t.maxZoom||!t.zoomingEnabled?i=!0:(t.zoom=s,a.push("zoom"))}if(r&&(!i||!e.cancelOnFailedZoom)&&t.panningEnabled){var l=e.pan;G(l.x)&&(t.pan.x=l.x,o=!1),G(l.y)&&(t.pan.y=l.y,o=!1),o||a.push("pan")}return a.length>0&&(a.push("viewport"),this.emit(a.join(" ")),this.notify("viewport")),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.emit("pan viewport"),this.notify("viewport")),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(W(e)){var n=e;e=this.mutableElements().filter(n)}else $(e)||(e=this.mutableElements());if(0!==e.length){var r=e.boundingBox(),a=this.width(),i=this.height();return{x:(a-(t=void 0===t?this._private.zoom:t)*(r.x1+r.x2))/2,y:(i-t*(r.y1+r.y2))/2}}}},reset:function(){return this._private.panningEnabled&&this._private.zoomingEnabled?(this.viewport({pan:{x:0,y:0},zoom:1}),this):this},invalidateSize:function(){this._private.sizeCache=null},size:function(){var e,t,n=this._private,r=n.container,a=this;return n.sizeCache=n.sizeCache||(r?(e=a.window().getComputedStyle(r),t=function(t){return parseFloat(e.getPropertyValue(t))},{width:r.clientWidth-t("padding-left")-t("padding-right"),height:r.clientHeight-t("padding-top")-t("padding-bottom")}):{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var e=this._private.pan,t=this._private.zoom,n=this.renderedExtent(),r={x1:(n.x1-e.x)/t,x2:(n.x2-e.x)/t,y1:(n.y1-e.y)/t,y2:(n.y2-e.y)/t};return r.w=r.x2-r.x1,r.h=r.y2-r.y1,r},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}},multiClickDebounceTime:function(e){return e?(this._private.multiClickDebounceTime=e,this):this._private.multiClickDebounceTime}};yu.centre=yu.center,yu.autolockNodes=yu.autolock,yu.autoungrabifyNodes=yu.autoungrabify;var mu={data:yo.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeData:yo.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),scratch:yo.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:yo.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0})};mu.attr=mu.data,mu.removeAttr=mu.removeData;var bu=function(e){var t=this,n=(e=ge({},e)).container;n&&!Z(n)&&Z(n[0])&&(n=n[0]);var r=n?n._cyreg:null;(r=r||{})&&r.cy&&(r.cy.destroy(),r={});var a=r.readies=r.readies||[];n&&(n._cyreg=r),r.cy=t;var i=void 0!==c&&void 0!==n&&!e.headless,o=e;o.layout=ge({name:i?"grid":"null"},o.layout),o.renderer=ge({name:i?"canvas":"null"},o.renderer);var s=function(e,t,n){return void 0!==t?t:void 0!==n?n:e},l=this._private={container:n,ready:!1,options:o,elements:new Nl(this),listeners:[],aniEles:new Nl(this),data:o.data||{},scratch:{},layout:null,renderer:null,destroyed:!1,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:s(!0,o.zoomingEnabled),userZoomingEnabled:s(!0,o.userZoomingEnabled),panningEnabled:s(!0,o.panningEnabled),userPanningEnabled:s(!0,o.userPanningEnabled),boxSelectionEnabled:s(!0,o.boxSelectionEnabled),autolock:s(!1,o.autolock,o.autolockNodes),autoungrabify:s(!1,o.autoungrabify,o.autoungrabifyNodes),autounselectify:s(!1,o.autounselectify),styleEnabled:void 0===o.styleEnabled?i:o.styleEnabled,zoom:G(o.zoom)?o.zoom:1,pan:{x:K(o.pan)&&G(o.pan.x)?o.pan.x:0,y:K(o.pan)&&G(o.pan.y)?o.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,multiClickDebounceTime:s(250,o.multiClickDebounceTime)};this.createEmitter(),this.selectionType(o.selectionType),this.zoomRange({min:o.minZoom,max:o.maxZoom});l.styleEnabled&&t.setStyle([]);var u=ge({},o,o.renderer);t.initRenderer(u);!function(e,t){if(e.some(re))return Yr.all(e).then(t);t(e)}([o.style,o.elements],(function(e){var n=e[0],i=e[1];l.styleEnabled&&t.style().append(n),function(e,n,r){t.notifications(!1);var a=t.mutableElements();a.length>0&&a.remove(),null!=e&&(K(e)||H(e))&&t.add(e),t.one("layoutready",(function(e){t.notifications(!0),t.emit(e),t.one("load",n),t.emitAndNotify("load")})).one("layoutstop",(function(){t.one("done",r),t.emit("done")}));var i=ge({},t._private.options.layout);i.eles=t.elements(),t.layout(i).run()}(i,(function(){t.startAnimationLoop(),l.ready=!0,U(o.ready)&&t.on("ready",o.ready);for(var e=0;e0,l=!!t.boundingBox,u=n.extent(),c=Qt(l?t.boundingBox:{x1:u.x1,y1:u.y1,w:u.w,h:u.h});if($(t.roots))e=t.roots;else if(H(t.roots)){for(var d=[],h=0;h0;){var D=P.shift(),_=C(D,S);if(_)D.outgoers().filter((function(e){return e.isNode()&&r.has(e)})).forEach(B);else if(null===_){rt("Detected double maximal shift for node `"+D.id()+"`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.");break}}}var A=0;if(t.avoidOverlap)for(var M=0;M0&&m[0].length<=3?i/2:0),s=2*Math.PI/m[r].length*a;return 0===r&&1===m[0].length&&(o=1),{x:U+o*Math.cos(s),y:K+o*Math.sin(s)}}var u=m[r].length,d=Math.max(1===u?0:l?(c.w-2*t.padding-G.w)/((t.grid?Q:u)-1):(c.w-2*t.padding-G.w)/((t.grid?Q:u)+1),A);return{x:U+(a+1-(u+1)/2)*d,y:K+(r+1-(V+1)/2)*Z}})),this};var Pu={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,radius:void 0,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function Su(e){this.options=ge({},Pu,e)}Su.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,a=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,i=r.nodes().not(":parent");t.sort&&(i=i.sort(t.sort));for(var o,s=Qt(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),l=s.x1+s.w/2,u=s.y1+s.h/2,c=(void 0===t.sweep?2*Math.PI-2*Math.PI/i.length:t.sweep)/Math.max(1,i.length-1),d=0,h=0;h1&&t.avoidOverlap){d*=1.75;var g=Math.cos(c)-Math.cos(0),y=Math.sin(c)-Math.sin(0),m=Math.sqrt(d*d/(g*g+y*y));o=Math.max(m,o)}return r.nodes().layoutPositions(this,t,(function(e,n){var r=t.startAngle+n*c*(a?1:-1),i=o*Math.cos(r),s=o*Math.sin(r);return{x:l+i,y:u+s}})),this};var Bu,Du={fit:!0,padding:30,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,height:void 0,width:void 0,spacingFactor:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function _u(e){this.options=ge({},Du,e)}_u.prototype.run=function(){for(var e=this.options,t=e,n=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,r=e.cy,a=t.eles,i=a.nodes().not(":parent"),o=Qt(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()}),s=o.x1+o.w/2,l=o.y1+o.h/2,u=[],c=0,d=0;d0)Math.abs(m[0].value-x.value)>=g&&(m=[],y.push(m));m.push(x)}var w=c+t.minNodeSpacing;if(!t.avoidOverlap){var E=y.length>0&&y[0].length>1,k=(Math.min(o.w,o.h)/2-w)/(y.length+E?1:0);w=Math.min(w,k)}for(var T=0,C=0;C1&&t.avoidOverlap){var D=Math.cos(B)-Math.cos(0),_=Math.sin(B)-Math.sin(0),A=Math.sqrt(w*w/(D*D+_*_));T=Math.max(A,T)}P.r=T,T+=w}if(t.equidistant){for(var M=0,R=0,I=0;I=e.numIter)&&(Vu(r,e),r.temperature=r.temperature*e.coolingFactor,!(r.temperature=e.animationThreshold&&i(),Ie(c)):($u(r,e),s())};c()}else{for(;u;)u=o(l),l++;$u(r,e),s()}return this},Mu.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.emit("layoutstop"),this},Mu.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var Ru=function(e,t,n){for(var r=n.eles.edges(),a=n.eles.nodes(),i=Qt(n.boundingBox?n.boundingBox:{x1:0,y1:0,w:e.width(),h:e.height()}),o={isCompound:e.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:a.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:r.size(),temperature:n.initialTemp,clientWidth:i.w,clientHeight:i.h,boundingBox:i},s=n.eles.components(),l={},u=0;u0){o.graphSet.push(w);for(u=0;ur.count?0:r.graph},Nu=function(e,t,n,r){var a=r.graphSet[n];if(-10)var s=(u=r.nodeOverlap*o)*a/(v=Math.sqrt(a*a+i*i)),l=u*i/v;else{var u,c=Yu(e,a,i),d=Yu(t,-1*a,-1*i),h=d.x-c.x,f=d.y-c.y,p=h*h+f*f,v=Math.sqrt(p);s=(u=(e.nodeRepulsion+t.nodeRepulsion)/p)*h/v,l=u*f/v}e.isLocked||(e.offsetX-=s,e.offsetY-=l),t.isLocked||(t.offsetX+=s,t.offsetY+=l)}},qu=function(e,t,n,r){if(n>0)var a=e.maxX-t.minX;else a=t.maxX-e.minX;if(r>0)var i=e.maxY-t.minY;else i=t.maxY-e.minY;return a>=0&&i>=0?Math.sqrt(a*a+i*i):0},Yu=function(e,t,n){var r=e.positionX,a=e.positionY,i=e.height||1,o=e.width||1,s=n/t,l=i/o,u={};return 0===t&&0n?(u.x=r,u.y=a+i/2,u):0t&&-1*l<=s&&s<=l?(u.x=r-o/2,u.y=a-o*n/2/t,u):0=l)?(u.x=r+i*t/2/n,u.y=a+i/2,u):0>n&&(s<=-1*l||s>=l)?(u.x=r-i*t/2/n,u.y=a-i/2,u):u},Wu=function(e,t){for(var n=0;n1){var p=t.gravity*d/f,v=t.gravity*h/f;c.offsetX+=p,c.offsetY+=v}}}}},Hu=function(e,t){var n=[],r=0,a=-1;for(n.push.apply(n,e.graphSet[0]),a+=e.graphSet[0].length;r<=a;){var i=n[r++],o=e.idToIndex[i],s=e.layoutNodes[o],l=s.children;if(0n)var a={x:n*e/r,y:n*t/r};else a={x:e,y:t};return a},Zu=function(e,t){var n=e.parentId;if(null!=n){var r=t.layoutNodes[t.idToIndex[n]],a=!1;return(null==r.maxX||e.maxX+r.padRight>r.maxX)&&(r.maxX=e.maxX+r.padRight,a=!0),(null==r.minX||e.minX-r.padLeftr.maxY)&&(r.maxY=e.maxY+r.padBottom,a=!0),(null==r.minY||e.minY-r.padTopp&&(d+=f+t.componentSpacing,c=0,h=0,f=0)}}},Qu={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,condense:!1,rows:void 0,cols:void 0,position:function(e){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(e,t){return!0},ready:void 0,stop:void 0,transform:function(e,t){return t}};function Ju(e){this.options=ge({},Qu,e)}Ju.prototype.run=function(){var e=this.options,t=e,n=e.cy,r=t.eles,a=r.nodes().not(":parent");t.sort&&(a=a.sort(t.sort));var i=Qt(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()});if(0===i.h||0===i.w)r.nodes().layoutPositions(this,t,(function(e){return{x:i.x1,y:i.y1}}));else{var o=a.size(),s=Math.sqrt(o*i.h/i.w),l=Math.round(s),u=Math.round(i.w/i.h*s),c=function(e){if(null==e)return Math.min(l,u);Math.min(l,u)==l?l=e:u=e},d=function(e){if(null==e)return Math.max(l,u);Math.max(l,u)==l?l=e:u=e},h=t.rows,f=null!=t.cols?t.cols:t.columns;if(null!=h&&null!=f)l=h,u=f;else if(null!=h&&null==f)l=h,u=Math.ceil(o/l);else if(null==h&&null!=f)u=f,l=Math.ceil(o/u);else if(u*l>o){var p=c(),v=d();(p-1)*v>=o?c(p-1):(v-1)*p>=o&&d(v-1)}else for(;u*l=o?d(y+1):c(g+1)}var m=i.w/u,b=i.h/l;if(t.condense&&(m=0,b=0),t.avoidOverlap)for(var x=0;x=u&&(A=0,_++)},R={},I=0;I(r=hn(e,t,x[w],x[w+1],x[w+2],x[w+3])))return g(n,r),!0}else if("bezier"===i.edgeType||"multibezier"===i.edgeType||"self"===i.edgeType||"compound"===i.edgeType)for(x=i.allpts,w=0;w+5(r=dn(e,t,x[w],x[w+1],x[w+2],x[w+3],x[w+4],x[w+5])))return g(n,r),!0;m=m||a.source,b=b||a.target;var E=o.getArrowWidth(l,c),k=[{name:"source",x:i.arrowStartX,y:i.arrowStartY,angle:i.srcArrowAngle},{name:"target",x:i.arrowEndX,y:i.arrowEndY,angle:i.tgtArrowAngle},{name:"mid-source",x:i.midX,y:i.midY,angle:i.midsrcArrowAngle},{name:"mid-target",x:i.midX,y:i.midY,angle:i.midtgtArrowAngle}];for(w=0;w0&&(y(m),y(b))}function b(e,t,n){return dt(e,t,n)}function x(n,r){var a,i=n._private,o=p;a=r?r+"-":"",n.boundingBox();var s=i.labelBounds[r||"main"],l=n.pstyle(a+"label").value;if("yes"===n.pstyle("text-events").strValue&&l){var u=b(i.rscratch,"labelX",r),c=b(i.rscratch,"labelY",r),d=b(i.rscratch,"labelAngle",r),h=n.pstyle(a+"text-margin-x").pfValue,f=n.pstyle(a+"text-margin-y").pfValue,v=s.x1-o-h,y=s.x2+o-h,m=s.y1-o-f,x=s.y2+o-f;if(d){var w=Math.cos(d),E=Math.sin(d),k=function(e,t){return{x:(e-=u)*w-(t-=c)*E+u,y:e*E+t*w+c}},T=k(v,m),C=k(v,x),P=k(y,m),S=k(y,x),B=[T.x+h,T.y+f,P.x+h,P.y+f,S.x+h,S.y+f,C.x+h,C.y+f];if(fn(e,t,B))return g(n),!0}else if(an(s,e,t))return g(n),!0}}n&&(l=l.interactive);for(var w=l.length-1;w>=0;w--){var E=l[w];E.isNode()?y(E)||x(E):m(E)||x(E)||x(E,"source")||x(E,"target")}return u},getAllInBox:function(e,t,n,r){var a,i,o=this.getCachedZSortedEles().interactive,s=2/this.cy.zoom(),l=[],u=Math.min(e,n),c=Math.max(e,n),d=Math.min(t,r),h=Math.max(t,r),f=Qt({x1:e=u,y1:t=d,x2:n=c,y2:r=h});function p(e,t,n){return dt(e,t,n)}function v(e,t){var n=e._private,r=s;e.boundingBox();var a=n.labelBounds.main;if(!a)return null;var i=p(n.rscratch,"labelX",t),o=p(n.rscratch,"labelY",t),l=p(n.rscratch,"labelAngle",t),u=e.pstyle("text-margin-x").pfValue,c=e.pstyle("text-margin-y").pfValue,d=a.x1-r-u,h=a.x2+r-u,f=a.y1-r-c,v=a.y2+r-c;if(l){var g=Math.cos(l),y=Math.sin(l),m=function(e,t){return{x:(e-=i)*g-(t-=o)*y+i,y:e*y+t*g+o}};return[m(d,f),m(h,f),m(h,v),m(d,v)]}return[{x:d,y:f},{x:h,y:f},{x:h,y:v},{x:d,y:v}]}for(var g=0;g0?-(Math.PI-i.ang):Math.PI+i.ang),Mc(t,n,Ac),vc=_c.nx*Ac.ny-_c.ny*Ac.nx,gc=_c.nx*Ac.nx-_c.ny*-Ac.ny,bc=Math.asin(Math.max(-1,Math.min(1,vc))),Math.abs(bc)<1e-6)return fc=t.x,pc=t.y,void(wc=kc=0);yc=1,mc=!1,gc<0?bc<0?bc=Math.PI+bc:(bc=Math.PI-bc,yc=-1,mc=!0):bc>0&&(yc=-1,mc=!0),kc=void 0!==t.radius?t.radius:r,xc=bc/2,Tc=Math.min(_c.len/2,Ac.len/2),a?(Ec=Math.abs(Math.cos(xc)*kc/Math.sin(xc)))>Tc?(Ec=Tc,wc=Math.abs(Ec*Math.sin(xc)/Math.cos(xc))):wc=kc:(Ec=Math.min(Tc,kc),wc=Math.abs(Ec*Math.sin(xc)/Math.cos(xc))),Sc=t.x+Ac.nx*Ec,Bc=t.y+Ac.ny*Ec,fc=Sc-Ac.ny*wc*yc,pc=Bc+Ac.nx*wc*yc,Cc=t.x+_c.nx*Ec,Pc=t.y+_c.ny*Ec,Dc=t};function Ic(e,t){0===t.radius?e.lineTo(t.cx,t.cy):e.arc(t.cx,t.cy,t.radius,t.startAngle,t.endAngle,t.counterClockwise)}function Nc(e,t,n,r){var a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4];return 0===r||0===t.radius?{cx:t.x,cy:t.y,radius:0,startX:t.x,startY:t.y,stopX:t.x,stopY:t.y,startAngle:void 0,endAngle:void 0,counterClockwise:void 0}:(Rc(e,t,n,r,a),{cx:fc,cy:pc,radius:wc,startX:Cc,startY:Pc,stopX:Sc,stopY:Bc,startAngle:_c.ang+Math.PI/2*yc,endAngle:Ac.ang-Math.PI/2*yc,counterClockwise:mc})}var Lc=.01,zc=Math.sqrt(.02),Oc={};function Vc(e){var t=[];if(null!=e){for(var n=0;n0?Math.max(e-t,0):Math.min(e+t,0)},S=P(T,E),B=P(C,k),D=!1;"auto"===g?v=Math.abs(S)>Math.abs(B)?a:r:g===l||g===s?(v=r,D=!0):g!==i&&g!==o||(v=a,D=!0);var _,A=v===r,M=A?B:S,R=A?C:T,I=Wt(R),N=!1;(D&&(m||x)||!(g===s&&R<0||g===l&&R>0||g===i&&R>0||g===o&&R<0)||(M=(I*=-1)*Math.abs(M),N=!0),m)?_=(b<0?1+b:b)*M:_=(b<0?M:0)+b*I;var L=function(e){return Math.abs(e)=Math.abs(M)},z=L(_),O=L(Math.abs(M)-Math.abs(_));if((z||O)&&!N)if(A){var V=Math.abs(R)<=d/2,F=Math.abs(T)<=h/2;if(V){var j=(u.x1+u.x2)/2,X=u.y1,q=u.y2;n.segpts=[j,X,j,q]}else if(F){var Y=(u.y1+u.y2)/2,W=u.x1,U=u.x2;n.segpts=[W,Y,U,Y]}else n.segpts=[u.x1,u.y2]}else{var H=Math.abs(R)<=c/2,K=Math.abs(C)<=f/2;if(H){var G=(u.y1+u.y2)/2,Z=u.x1,$=u.x2;n.segpts=[Z,G,$,G]}else if(K){var Q=(u.x1+u.x2)/2,J=u.y1,ee=u.y2;n.segpts=[Q,J,Q,ee]}else n.segpts=[u.x2,u.y1]}else if(A){var te=u.y1+_+(p?d/2*I:0),ne=u.x1,re=u.x2;n.segpts=[ne,te,re,te]}else{var ae=u.x1+_+(p?c/2*I:0),ie=u.y1,oe=u.y2;n.segpts=[ae,ie,ae,oe]}if(n.isRound){var se=e.pstyle("taxi-radius").value,le="arc-radius"===e.pstyle("radius-type").value[0];n.radii=new Array(n.segpts.length/2).fill(se),n.isArcRadius=new Array(n.segpts.length/2).fill(le)}},Oc.tryToCorrectInvalidPoints=function(e,t){var n=e._private.rscratch;if("bezier"===n.edgeType){var r=t.srcPos,a=t.tgtPos,i=t.srcW,o=t.srcH,s=t.tgtW,l=t.tgtH,u=t.srcShape,c=t.tgtShape,d=t.srcCornerRadius,h=t.tgtCornerRadius,f=t.srcRs,p=t.tgtRs,v=!G(n.startX)||!G(n.startY),g=!G(n.arrowStartX)||!G(n.arrowStartY),y=!G(n.endX)||!G(n.endY),m=!G(n.arrowEndX)||!G(n.arrowEndY),b=3*(this.getArrowWidth(e.pstyle("width").pfValue,e.pstyle("arrow-scale").value)*this.arrowShapeWidth),x=Ut({x:n.ctrlpts[0],y:n.ctrlpts[1]},{x:n.startX,y:n.startY}),w=xv.poolIndex()){var g=p;p=v,v=g}var y=d.srcPos=p.position(),m=d.tgtPos=v.position(),b=d.srcW=p.outerWidth(),x=d.srcH=p.outerHeight(),E=d.tgtW=v.outerWidth(),k=d.tgtH=v.outerHeight(),T=d.srcShape=n.nodeShapes[t.getNodeShape(p)],C=d.tgtShape=n.nodeShapes[t.getNodeShape(v)],P=d.srcCornerRadius="auto"===p.pstyle("corner-radius").value?"auto":p.pstyle("corner-radius").pfValue,S=d.tgtCornerRadius="auto"===v.pstyle("corner-radius").value?"auto":v.pstyle("corner-radius").pfValue,B=d.tgtRs=v._private.rscratch,D=d.srcRs=p._private.rscratch;d.dirCounts={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0};for(var _=0;_=zc||(Y=Math.sqrt(Math.max(q*q,Lc)+Math.max(X*X,Lc)));var W=d.vector={x:q,y:X},U=d.vectorNorm={x:W.x/Y,y:W.y/Y},H={x:-U.y,y:U.x};d.nodesOverlap=!G(Y)||C.checkPoint(L[0],L[1],0,E,k,m.x,m.y,S,B)||T.checkPoint(O[0],O[1],0,b,x,y.x,y.y,P,D),d.vectorNormInverse=H,e={nodesOverlap:d.nodesOverlap,dirCounts:d.dirCounts,calculatedIntersection:!0,hasBezier:d.hasBezier,hasUnbundled:d.hasUnbundled,eles:d.eles,srcPos:m,srcRs:B,tgtPos:y,tgtRs:D,srcW:E,srcH:k,tgtW:b,tgtH:x,srcIntn:V,tgtIntn:z,srcShape:C,tgtShape:T,posPts:{x1:j.x2,y1:j.y2,x2:j.x1,y2:j.y1},intersectionPts:{x1:F.x2,y1:F.y2,x2:F.x1,y2:F.y1},vector:{x:-W.x,y:-W.y},vectorNorm:{x:-U.x,y:-U.y},vectorNormInverse:{x:-H.x,y:-H.y}}}var K=N?e:d;M.nodesOverlap=K.nodesOverlap,M.srcIntn=K.srcIntn,M.tgtIntn=K.tgtIntn,M.isRound=R.startsWith("round"),r&&(p.isParent()||p.isChild()||v.isParent()||v.isChild())&&(p.parents().anySame(v)||v.parents().anySame(p)||p.same(v)&&p.isParent())?t.findCompoundLoopPoints(A,K,_,I):p===v?t.findLoopPoints(A,K,_,I):R.endsWith("segments")?t.findSegmentsPoints(A,K):R.endsWith("taxi")?t.findTaxiPoints(A,K):"straight"===R||!I&&d.eles.length%2==1&&_===Math.floor(d.eles.length/2)?t.findStraightEdgePoints(A):t.findBezierPoints(A,K,_,I,N),t.findEndpoints(A),t.tryToCorrectInvalidPoints(A,K),t.checkForInvalidEdgeWarning(A),t.storeAllpts(A),t.storeEdgeProjections(A),t.calculateArrowAngles(A),t.recalculateEdgeLabelProjections(A),t.calculateLabelAngles(A)}},w=0;w0){var J=f,ee=Ht(J,Xt(i)),te=Ht(J,Xt(Q)),ne=ee;if(te2)Ht(J,{x:Q[2],y:Q[3]})0){var ge=p,ye=Ht(ge,Xt(i)),me=Ht(ge,Xt(ve)),be=ye;if(me2)Ht(ge,{x:ve[2],y:ve[3]})=u||m){c={cp:v,segment:y};break}}if(c)break}var b=c.cp,x=c.segment,w=(u-h)/x.length,E=x.t1-x.t0,k=s?x.t0+E*w:x.t1-E*w;k=$t(0,k,1),t=Zt(b.p0,b.p1,b.p2,k),a=function(e,t,n,r){var a=$t(0,r-.001,1),i=$t(0,r+.001,1),o=Zt(e,t,n,a),s=Zt(e,t,n,i);return Wc(o,s)}(b.p0,b.p1,b.p2,k);break;case"straight":case"segments":case"haystack":for(var T,C,P,S,B=0,D=r.allpts.length,_=0;_+3=u));_+=2);var A=(u-C)/T;A=$t(0,A,1),t=function(e,t,n,r){var a=t.x-e.x,i=t.y-e.y,o=Ut(e,t),s=a/o,l=i/o;return n=null==n?0:n,r=null!=r?r:n*o,{x:e.x+s*r,y:e.y+l*r}}(P,S,A),a=Wc(P,S)}o("labelX",n,t.x),o("labelY",n,t.y),o("labelAutoAngle",n,a)}};u("source"),u("target"),this.applyLabelDimensions(e)}},qc.applyLabelDimensions=function(e){this.applyPrefixedLabelDimensions(e),e.isEdge()&&(this.applyPrefixedLabelDimensions(e,"source"),this.applyPrefixedLabelDimensions(e,"target"))},qc.applyPrefixedLabelDimensions=function(e,t){var n=e._private,r=this.getLabelText(e,t),a=Ye(r,e._private.labelDimsKey);if(dt(n.rscratch,"prefixedLabelDimsKey",t)!==a){ht(n.rscratch,"prefixedLabelDimsKey",t,a);var i=this.calculateLabelDimensions(e,r),o=e.pstyle("line-height").pfValue,s=e.pstyle("text-wrap").strValue,l=dt(n.rscratch,"labelWrapCachedLines",t)||[],u="wrap"!==s?1:Math.max(l.length,1),c=i.height/u,d=c*o,h=i.width,f=i.height+(u-1)*(o-1)*c;ht(n.rstyle,"labelWidth",t,h),ht(n.rscratch,"labelWidth",t,h),ht(n.rstyle,"labelHeight",t,f),ht(n.rscratch,"labelHeight",t,f),ht(n.rscratch,"labelLineHeight",t,d)}},qc.getLabelText=function(e,t){var n=e._private,a=t?t+"-":"",i=e.pstyle(a+"label").strValue,o=e.pstyle("text-transform").value,s=function(e,r){return r?(ht(n.rscratch,e,t,r),r):dt(n.rscratch,e,t)};if(!i)return"";"none"==o||("uppercase"==o?i=i.toUpperCase():"lowercase"==o&&(i=i.toLowerCase()));var l=e.pstyle("text-wrap").value;if("wrap"===l){var u=s("labelKey");if(null!=u&&s("labelWrapKey")===u)return s("labelWrapCachedText");for(var c=i.split("\n"),d=e.pstyle("text-max-width").pfValue,h="anywhere"===e.pstyle("text-overflow-wrap").value,f=[],p=/[\s\u200b]+|$/g,v=0;vd){var b,x="",w=0,E=r(g.matchAll(p));try{for(E.s();!(b=E.n()).done;){var k=b.value,T=k[0],C=g.substring(w,k.index);w=k.index+T.length;var P=0===x.length?C:x+C+T;this.calculateLabelDimensions(e,P).width<=d?x+=C+T:(x&&f.push(x),x=C+T)}}catch(e){E.e(e)}finally{E.f()}x.match(/^[\s\u200b]+$/)||f.push(x)}else f.push(g)}s("labelWrapCachedLines",f),i=s("labelWrapCachedText",f.join("\n")),s("labelWrapKey",u)}else if("ellipsis"===l){var S=e.pstyle("text-max-width").pfValue,B="",D=!1;if(this.calculateLabelDimensions(e,i).widthS)break;B+=i[_],_===i.length-1&&(D=!0)}return D||(B+="…"),B}return i},qc.getLabelJustification=function(e){var t=e.pstyle("text-justification").strValue,n=e.pstyle("text-halign").strValue;if("auto"!==t)return t;if(!e.isNode())return"center";switch(n){case"left":return"right";case"right":return"left";default:return"center"}},qc.calculateLabelDimensions=function(e,t){var n=this.cy.window().document,r=e.pstyle("font-style").strValue,a=e.pstyle("font-size").pfValue,i=e.pstyle("font-family").strValue,o=e.pstyle("font-weight").strValue,s=this.labelCalcCanvas,l=this.labelCalcCanvasContext;if(!s){s=this.labelCalcCanvas=n.createElement("canvas"),l=this.labelCalcCanvasContext=s.getContext("2d");var u=s.style;u.position="absolute",u.left="-9999px",u.top="-9999px",u.zIndex="-1",u.visibility="hidden",u.pointerEvents="none"}l.font="".concat(r," ").concat(o," ").concat(a,"px ").concat(i);for(var c=0,d=0,h=t.split("\n"),f=0;f1&&void 0!==arguments[1])||arguments[1];if(t.merge(e),n)for(var r=0;r=e.desktopTapThreshold2}var P=a(t);g&&(e.hoverData.tapholdCancelled=!0);n=!0,r(v,["mousemove","vmousemove","tapdrag"],t,{x:c[0],y:c[1]});var S=function(e){return{originalEvent:t,type:e,position:{x:c[0],y:c[1]}}},B=function(){e.data.bgActivePosistion=void 0,e.hoverData.selecting||o.emit(S("boxstart")),p[4]=1,e.hoverData.selecting=!0,e.redrawHint("select",!0),e.redraw()};if(3===e.hoverData.which){if(g){var D=S("cxtdrag");b?b.emit(D):o.emit(D),e.hoverData.cxtDragged=!0,e.hoverData.cxtOver&&v===e.hoverData.cxtOver||(e.hoverData.cxtOver&&e.hoverData.cxtOver.emit(S("cxtdragout")),e.hoverData.cxtOver=v,v&&v.emit(S("cxtdragover")))}}else if(e.hoverData.dragging){if(n=!0,o.panningEnabled()&&o.userPanningEnabled()){var _;if(e.hoverData.justStartedPan){var A=e.hoverData.mdownPos;_={x:(c[0]-A[0])*s,y:(c[1]-A[1])*s},e.hoverData.justStartedPan=!1}else _={x:x[0]*s,y:x[1]*s};o.panBy(_),o.emit(S("dragpan")),e.hoverData.dragged=!0}c=e.projectIntoViewport(t.clientX,t.clientY)}else if(1!=p[4]||null!=b&&!b.pannable()){if(b&&b.pannable()&&b.active()&&b.unactivate(),b&&b.grabbed()||v==y||(y&&r(y,["mouseout","tapdragout"],t,{x:c[0],y:c[1]}),v&&r(v,["mouseover","tapdragover"],t,{x:c[0],y:c[1]}),e.hoverData.last=v),b)if(g){if(o.boxSelectionEnabled()&&P)b&&b.grabbed()&&(d(w),b.emit(S("freeon")),w.emit(S("free")),e.dragData.didDrag&&(b.emit(S("dragfreeon")),w.emit(S("dragfree")))),B();else if(b&&b.grabbed()&&e.nodeIsDraggable(b)){var M=!e.dragData.didDrag;M&&e.redrawHint("eles",!0),e.dragData.didDrag=!0,e.hoverData.draggingEles||u(w,{inDragLayer:!0});var R={x:0,y:0};if(G(x[0])&&G(x[1])&&(R.x+=x[0],R.y+=x[1],M)){var I=e.hoverData.dragDelta;I&&G(I[0])&&G(I[1])&&(R.x+=I[0],R.y+=I[1])}e.hoverData.draggingEles=!0,w.silentShift(R).emit(S("position")).emit(S("drag")),e.redrawHint("drag",!0),e.redraw()}}else!function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];0===t.length?(t.push(x[0]),t.push(x[1])):(t[0]+=x[0],t[1]+=x[1])}();n=!0}else if(g){if(e.hoverData.dragging||!o.boxSelectionEnabled()||!P&&o.panningEnabled()&&o.userPanningEnabled()){if(!e.hoverData.selecting&&o.panningEnabled()&&o.userPanningEnabled()){i(b,e.hoverData.downs)&&(e.hoverData.dragging=!0,e.hoverData.justStartedPan=!0,p[4]=0,e.data.bgActivePosistion=Xt(h),e.redrawHint("select",!0),e.redraw())}}else B();b&&b.pannable()&&b.active()&&b.unactivate()}return p[2]=c[0],p[3]=c[1],n?(t.stopPropagation&&t.stopPropagation(),t.preventDefault&&t.preventDefault(),!1):void 0}}),!1),e.registerBinding(t,"mouseup",(function(t){if((1!==e.hoverData.which||1===t.which||!e.hoverData.capture)&&e.hoverData.capture){e.hoverData.capture=!1;var i=e.cy,o=e.projectIntoViewport(t.clientX,t.clientY),s=e.selection,l=e.findNearestElement(o[0],o[1],!0,!1),u=e.dragData.possibleDragElements,c=e.hoverData.down,h=a(t);e.data.bgActivePosistion&&(e.redrawHint("select",!0),e.redraw()),e.hoverData.tapholdCancelled=!0,e.data.bgActivePosistion=void 0,c&&c.unactivate();var f=function(e){return{originalEvent:t,type:e,position:{x:o[0],y:o[1]}}};if(3===e.hoverData.which){var p=f("cxttapend");if(c?c.emit(p):i.emit(p),!e.hoverData.cxtDragged){var v=f("cxttap");c?c.emit(v):i.emit(v)}e.hoverData.cxtDragged=!1,e.hoverData.which=null}else if(1===e.hoverData.which){if(r(l,["mouseup","tapend","vmouseup"],t,{x:o[0],y:o[1]}),e.dragData.didDrag||e.hoverData.dragged||e.hoverData.selecting||e.hoverData.isOverThresholdDrag||(r(c,["click","tap","vclick"],t,{x:o[0],y:o[1]}),x=!1,t.timeStamp-w<=i.multiClickDebounceTime()?(b&&clearTimeout(b),x=!0,w=null,r(c,["dblclick","dbltap","vdblclick"],t,{x:o[0],y:o[1]})):(b=setTimeout((function(){x||r(c,["oneclick","onetap","voneclick"],t,{x:o[0],y:o[1]})}),i.multiClickDebounceTime()),w=t.timeStamp)),null!=c||e.dragData.didDrag||e.hoverData.selecting||e.hoverData.dragged||a(t)||(i.$(n).unselect(["tapunselect"]),u.length>0&&e.redrawHint("eles",!0),e.dragData.possibleDragElements=u=i.collection()),l!=c||e.dragData.didDrag||e.hoverData.selecting||null!=l&&l._private.selectable&&(e.hoverData.dragging||("additive"===i.selectionType()||h?l.selected()?l.unselect(["tapunselect"]):l.select(["tapselect"]):h||(i.$(n).unmerge(l).unselect(["tapunselect"]),l.select(["tapselect"]))),e.redrawHint("eles",!0)),e.hoverData.selecting){var g=i.collection(e.getAllInBox(s[0],s[1],s[2],s[3]));e.redrawHint("select",!0),g.length>0&&e.redrawHint("eles",!0),i.emit(f("boxend"));var y=function(e){return e.selectable()&&!e.selected()};"additive"===i.selectionType()||h||i.$(n).unmerge(g).unselect(),g.emit(f("box")).stdFilter(y).select().emit(f("boxselect")),e.redraw()}if(e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint("select",!0),e.redrawHint("eles",!0),e.redraw()),!s[4]){e.redrawHint("drag",!0),e.redrawHint("eles",!0);var m=c&&c.grabbed();d(u),m&&(c.emit(f("freeon")),u.emit(f("free")),e.dragData.didDrag&&(c.emit(f("dragfreeon")),u.emit(f("dragfree"))))}}s[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.hoverData.isOverThresholdDrag=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[],e.hoverData.mdownPos=null,e.hoverData.mdownGPos=null,e.hoverData.which=null}}),!1);var k,T,C,P,S,B,D,_,A,M,R,I,N,L,z=[],O=1e5,V=function(t){var n=!1,r=t.deltaY;if(null==r&&(null!=t.wheelDeltaY?r=t.wheelDeltaY/4:null!=t.wheelDelta&&(r=t.wheelDelta/4)),null==k)if(z.length>=4){var a=z;if(k=function(e,t){for(var n=0;n5}if(k)for(var o=0;o5&&(r=5*Wt(r)),h=r/-250,k&&(h/=O,h*=3),h*=e.wheelSensitivity,1===t.deltaMode&&(h*=33);var f=s.zoom()*Math.pow(10,h);"gesturechange"===t.type&&(f=e.gestureStartZoom*t.scale),s.zoom({level:f,renderedPosition:{x:d[0],y:d[1]}}),s.emit({type:"gesturechange"===t.type?"pinchzoom":"scrollzoom",originalEvent:t,position:{x:c[0],y:c[1]}})}}};e.registerBinding(e.container,"wheel",V,!0),e.registerBinding(t,"scroll",(function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout((function(){e.scrollingPage=!1}),250)}),!0),e.registerBinding(e.container,"gesturestart",(function(t){e.gestureStartZoom=e.cy.zoom(),e.hasTouchStarted||t.preventDefault()}),!0),e.registerBinding(e.container,"gesturechange",(function(t){e.hasTouchStarted||V(t)}),!0),e.registerBinding(e.container,"mouseout",(function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:"mouseout",position:{x:n[0],y:n[1]}})}),!1),e.registerBinding(e.container,"mouseover",(function(t){var n=e.projectIntoViewport(t.clientX,t.clientY);e.cy.emit({originalEvent:t,type:"mouseover",position:{x:n[0],y:n[1]}})}),!1);var F,j,X,q,Y,W,U,H=function(e,t,n,r){return Math.sqrt((n-e)*(n-e)+(r-t)*(r-t))},K=function(e,t,n,r){return(n-e)*(n-e)+(r-t)*(r-t)};if(e.registerBinding(e.container,"touchstart",F=function(t){if(e.hasTouchStarted=!0,m(t)){f(),e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,a=e.touchData.now,i=e.touchData.earlier;if(t.touches[0]){var o=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);a[0]=o[0],a[1]=o[1]}if(t.touches[1]){o=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);a[2]=o[0],a[3]=o[1]}if(t.touches[2]){o=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);a[4]=o[0],a[5]=o[1]}var l=function(e){return{originalEvent:t,type:e,position:{x:a[0],y:a[1]}}};if(t.touches[1]){e.touchData.singleTouchMoved=!0,d(e.dragData.touchDragEles);var h=e.findContainerClientCoords();M=h[0],R=h[1],I=h[2],N=h[3],T=t.touches[0].clientX-M,C=t.touches[0].clientY-R,P=t.touches[1].clientX-M,S=t.touches[1].clientY-R,L=0<=T&&T<=I&&0<=P&&P<=I&&0<=C&&C<=N&&0<=S&&S<=N;var p=n.pan(),v=n.zoom();B=H(T,C,P,S),D=K(T,C,P,S),A=[((_=[(T+P)/2,(C+S)/2])[0]-p.x)/v,(_[1]-p.y)/v];if(D<4e4&&!t.touches[2]){var g=e.findNearestElement(a[0],a[1],!0,!0),y=e.findNearestElement(a[2],a[3],!0,!0);return g&&g.isNode()?(g.activate().emit(l("cxttapstart")),e.touchData.start=g):y&&y.isNode()?(y.activate().emit(l("cxttapstart")),e.touchData.start=y):n.emit(l("cxttapstart")),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!0,e.touchData.cxtDragged=!1,e.data.bgActivePosistion=void 0,void e.redraw()}}if(t.touches[2])n.boxSelectionEnabled()&&t.preventDefault();else if(t.touches[1]);else if(t.touches[0]){var b=e.findNearestElements(a[0],a[1],!0,!0),x=b[0];if(null!=x&&(x.activate(),e.touchData.start=x,e.touchData.starts=b,e.nodeIsGrabbable(x))){var w=e.dragData.touchDragEles=n.collection(),E=null;e.redrawHint("eles",!0),e.redrawHint("drag",!0),x.selected()?(E=n.$((function(t){return t.selected()&&e.nodeIsGrabbable(t)})),u(E,{addToList:w})):c(x,{addToList:w}),s(x),x.emit(l("grabon")),E?E.forEach((function(e){e.emit(l("grab"))})):x.emit(l("grab"))}r(x,["touchstart","tapstart","vmousedown"],t,{x:a[0],y:a[1]}),null==x&&(e.data.bgActivePosistion={x:o[0],y:o[1]},e.redrawHint("select",!0),e.redraw()),e.touchData.singleTouchMoved=!1,e.touchData.singleTouchStartTime=+new Date,clearTimeout(e.touchData.tapholdTimeout),e.touchData.tapholdTimeout=setTimeout((function(){!1!==e.touchData.singleTouchMoved||e.pinching||e.touchData.selecting||r(e.touchData.start,["taphold"],t,{x:a[0],y:a[1]})}),e.tapholdDuration)}if(t.touches.length>=1){for(var k=e.touchData.startPosition=[null,null,null,null,null,null],z=0;z=e.touchTapThreshold2}if(n&&e.touchData.cxt){t.preventDefault();var E=t.touches[0].clientX-M,k=t.touches[0].clientY-R,_=t.touches[1].clientX-M,I=t.touches[1].clientY-R,N=K(E,k,_,I);if(N/D>=2.25||N>=22500){e.touchData.cxt=!1,e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var z=p("cxttapend");e.touchData.start?(e.touchData.start.unactivate().emit(z),e.touchData.start=null):o.emit(z)}}if(n&&e.touchData.cxt){z=p("cxtdrag");e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),e.touchData.start?e.touchData.start.emit(z):o.emit(z),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var O=e.findNearestElement(s[0],s[1],!0,!0);e.touchData.cxtOver&&O===e.touchData.cxtOver||(e.touchData.cxtOver&&e.touchData.cxtOver.emit(p("cxtdragout")),e.touchData.cxtOver=O,O&&O.emit(p("cxtdragover")))}else if(n&&t.touches[2]&&o.boxSelectionEnabled())t.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting||o.emit(p("boxstart")),e.touchData.selecting=!0,e.touchData.didSelect=!0,a[4]=1,a&&0!==a.length&&void 0!==a[0]?(a[2]=(s[0]+s[2]+s[4])/3,a[3]=(s[1]+s[3]+s[5])/3):(a[0]=(s[0]+s[2]+s[4])/3,a[1]=(s[1]+s[3]+s[5])/3,a[2]=(s[0]+s[2]+s[4])/3+1,a[3]=(s[1]+s[3]+s[5])/3+1),e.redrawHint("select",!0),e.redraw();else if(n&&t.touches[1]&&!e.touchData.didSelect&&o.zoomingEnabled()&&o.panningEnabled()&&o.userZoomingEnabled()&&o.userPanningEnabled()){if(t.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),te=e.dragData.touchDragEles){e.redrawHint("drag",!0);for(var V=0;V0&&!e.hoverData.draggingEles&&!e.swipePanning&&null!=e.data.bgActivePosistion&&(e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),e.redraw())}},!1),e.registerBinding(t,"touchcancel",X=function(t){var n=e.touchData.start;e.touchData.capture=!1,n&&n.unactivate()}),e.registerBinding(t,"touchend",q=function(t){var a=e.touchData.start;if(e.touchData.capture){0===t.touches.length&&(e.touchData.capture=!1),t.preventDefault();var i=e.selection;e.swipePanning=!1,e.hoverData.draggingEles=!1;var o=e.cy,s=o.zoom(),l=e.touchData.now,u=e.touchData.earlier;if(t.touches[0]){var c=e.projectIntoViewport(t.touches[0].clientX,t.touches[0].clientY);l[0]=c[0],l[1]=c[1]}if(t.touches[1]){c=e.projectIntoViewport(t.touches[1].clientX,t.touches[1].clientY);l[2]=c[0],l[3]=c[1]}if(t.touches[2]){c=e.projectIntoViewport(t.touches[2].clientX,t.touches[2].clientY);l[4]=c[0],l[5]=c[1]}var h,f=function(e){return{originalEvent:t,type:e,position:{x:l[0],y:l[1]}}};if(a&&a.unactivate(),e.touchData.cxt){if(h=f("cxttapend"),a?a.emit(h):o.emit(h),!e.touchData.cxtDragged){var p=f("cxttap");a?a.emit(p):o.emit(p)}return e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!1,e.touchData.start=null,void e.redraw()}if(!t.touches[2]&&o.boxSelectionEnabled()&&e.touchData.selecting){e.touchData.selecting=!1;var v=o.collection(e.getAllInBox(i[0],i[1],i[2],i[3]));i[0]=void 0,i[1]=void 0,i[2]=void 0,i[3]=void 0,i[4]=0,e.redrawHint("select",!0),o.emit(f("boxend"));v.emit(f("box")).stdFilter((function(e){return e.selectable()&&!e.selected()})).select().emit(f("boxselect")),v.nonempty()&&e.redrawHint("eles",!0),e.redraw()}if(null!=a&&a.unactivate(),t.touches[2])e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);else if(t.touches[1]);else if(t.touches[0]);else if(!t.touches[0]){e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var g=e.dragData.touchDragEles;if(null!=a){var y=a._private.grabbed;d(g),e.redrawHint("drag",!0),e.redrawHint("eles",!0),y&&(a.emit(f("freeon")),g.emit(f("free")),e.dragData.didDrag&&(a.emit(f("dragfreeon")),g.emit(f("dragfree")))),r(a,["touchend","tapend","vmouseup","tapdragout"],t,{x:l[0],y:l[1]}),a.unactivate(),e.touchData.start=null}else{var m=e.findNearestElement(l[0],l[1],!0,!0);r(m,["touchend","tapend","vmouseup","tapdragout"],t,{x:l[0],y:l[1]})}var b=e.touchData.startPosition[0]-l[0],x=b*b,w=e.touchData.startPosition[1]-l[1],E=(x+w*w)*s*s;e.touchData.singleTouchMoved||(a||o.$(":selected").unselect(["tapunselect"]),r(a,["tap","vclick"],t,{x:l[0],y:l[1]}),Y=!1,t.timeStamp-U<=o.multiClickDebounceTime()?(W&&clearTimeout(W),Y=!0,U=null,r(a,["dbltap","vdblclick"],t,{x:l[0],y:l[1]})):(W=setTimeout((function(){Y||r(a,["onetap","voneclick"],t,{x:l[0],y:l[1]})}),o.multiClickDebounceTime()),U=t.timeStamp)),null!=a&&!e.dragData.didDrag&&a._private.selectable&&E2){for(var f=[c[0],c[1]],p=Math.pow(f[0]-e,2)+Math.pow(f[1]-t,2),v=1;v0)return v[0]}return null},f=Object.keys(d),p=0;p0?u:ln(a,i,e,t,n,r,o,s)},checkPoint:function(e,t,n,r,a,i,o,s){var l=2*(s="auto"===s?Sn(r,a):s);if(pn(e,t,this.points,i,o,r,a-l,[0,-1],n))return!0;if(pn(e,t,this.points,i,o,r-l,a,[0,-1],n))return!0;var u=r/2+2*n,c=a/2+2*n;return!!fn(e,t,[i-u,o-c,i-u,o,i+u,o,i+u,o-c])||(!!yn(e,t,l,l,i+r/2-s,o+a/2-s,n)||!!yn(e,t,l,l,i-r/2+s,o+a/2-s,n))}}},Jc.registerNodeShapes=function(){var e=this.nodeShapes={},t=this;this.generateEllipse(),this.generatePolygon("triangle",Tn(3,0)),this.generateRoundPolygon("round-triangle",Tn(3,0)),this.generatePolygon("rectangle",Tn(4,0)),e.square=e.rectangle,this.generateRoundRectangle(),this.generateCutRectangle(),this.generateBarrel(),this.generateBottomRoundrectangle();var n=[0,1,1,0,0,-1,-1,0];this.generatePolygon("diamond",n),this.generateRoundPolygon("round-diamond",n),this.generatePolygon("pentagon",Tn(5,0)),this.generateRoundPolygon("round-pentagon",Tn(5,0)),this.generatePolygon("hexagon",Tn(6,0)),this.generateRoundPolygon("round-hexagon",Tn(6,0)),this.generatePolygon("heptagon",Tn(7,0)),this.generateRoundPolygon("round-heptagon",Tn(7,0)),this.generatePolygon("octagon",Tn(8,0)),this.generateRoundPolygon("round-octagon",Tn(8,0));var r=new Array(20),a=Pn(5,0),i=Pn(5,Math.PI/5),o=.5*(3-Math.sqrt(5));o*=1.57;for(var s=0;s=e.deqFastCost*v)break}else if(a){if(f>=e.deqCost*l||f>=e.deqAvgCost*s)break}else if(p>=e.deqNoDrawCost*ad)break;var g=e.deq(t,d,c);if(!(g.length>0))break;for(var y=0;y0&&(e.onDeqd(t,u),!a&&e.shouldRedraw(t,u,d,c)&&r())}),a(t))}}},od=function(){return n((function e(n){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Qe;t(this,e),this.idsByKey=new ft,this.keyForId=new ft,this.cachesByLvl=new ft,this.lvls=[],this.getKey=n,this.doesEleInvalidateKey=r}),[{key:"getIdsFor",value:function(e){null==e&&tt("Can not get id list for null key");var t=this.idsByKey,n=this.idsByKey.get(e);return n||(n=new vt,t.set(e,n)),n}},{key:"addIdForKey",value:function(e,t){null!=e&&this.getIdsFor(e).add(t)}},{key:"deleteIdForKey",value:function(e,t){null!=e&&this.getIdsFor(e).delete(t)}},{key:"getNumberOfIdsForKey",value:function(e){return null==e?0:this.getIdsFor(e).size}},{key:"updateKeyMappingFor",value:function(e){var t=e.id(),n=this.keyForId.get(t),r=this.getKey(e);this.deleteIdForKey(n,t),this.addIdForKey(r,t),this.keyForId.set(t,r)}},{key:"deleteKeyMappingFor",value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteIdForKey(n,t),this.keyForId.delete(t)}},{key:"keyHasChangedFor",value:function(e){var t=e.id();return this.keyForId.get(t)!==this.getKey(e)}},{key:"isInvalid",value:function(e){return this.keyHasChangedFor(e)||this.doesEleInvalidateKey(e)}},{key:"getCachesAt",value:function(e){var t=this.cachesByLvl,n=this.lvls,r=t.get(e);return r||(r=new ft,t.set(e,r),n.push(e)),r}},{key:"getCache",value:function(e,t){return this.getCachesAt(t).get(e)}},{key:"get",value:function(e,t){var n=this.getKey(e),r=this.getCache(n,t);return null!=r&&this.updateKeyMappingFor(e),r}},{key:"getForCachedKey",value:function(e,t){var n=this.keyForId.get(e.id());return this.getCache(n,t)}},{key:"hasCache",value:function(e,t){return this.getCachesAt(t).has(e)}},{key:"has",value:function(e,t){var n=this.getKey(e);return this.hasCache(n,t)}},{key:"setCache",value:function(e,t,n){n.key=e,this.getCachesAt(t).set(e,n)}},{key:"set",value:function(e,t,n){var r=this.getKey(e);this.setCache(r,t,n),this.updateKeyMappingFor(e)}},{key:"deleteCache",value:function(e,t){this.getCachesAt(t).delete(e)}},{key:"delete",value:function(e,t){var n=this.getKey(e);this.deleteCache(n,t)}},{key:"invalidateKey",value:function(e){var t=this;this.lvls.forEach((function(n){return t.deleteCache(e,n)}))}},{key:"invalidate",value:function(e){var t=e.id(),n=this.keyForId.get(t);this.deleteKeyMappingFor(e);var r=this.doesEleInvalidateKey(e);return r&&this.invalidateKey(n),r||0===this.getNumberOfIdsForKey(n)}}])}(),sd=7.99,ld={dequeue:"dequeue",downscale:"downscale",highQuality:"highQuality"},ud=lt({getKey:null,doesEleInvalidateKey:Qe,drawElement:null,getBoundingBox:null,getRotationPoint:null,getRotationOffset:null,isVisible:$e,allowEdgeTxrCaching:!0,allowParentTxrCaching:!0}),cd=function(e,t){var n=this;n.renderer=e,n.onDequeues=[];var r=ud(t);ge(n,r),n.lookup=new od(r.getKey,r.doesEleInvalidateKey),n.setupDequeueing()},dd=cd.prototype;dd.reasons=ld,dd.getTextureQueue=function(e){var t=this;return t.eleImgCaches=t.eleImgCaches||{},t.eleImgCaches[e]=t.eleImgCaches[e]||[]},dd.getRetiredTextureQueue=function(e){var t=this.eleImgCaches.retired=this.eleImgCaches.retired||{};return t[e]=t[e]||[]},dd.getElementQueue=function(){return this.eleCacheQueue=this.eleCacheQueue||new Pt((function(e,t){return t.reqs-e.reqs}))},dd.getElementKeyToQueue=function(){return this.eleKeyToCacheQueue=this.eleKeyToCacheQueue||{}},dd.getElement=function(e,t,n,r,a){var i=this,o=this.renderer,s=o.cy.zoom(),l=this.lookup;if(!t||0===t.w||0===t.h||isNaN(t.w)||isNaN(t.h)||!e.visible()||e.removed())return null;if(!i.allowEdgeTxrCaching&&e.isEdge()||!i.allowParentTxrCaching&&e.isParent())return null;if(null==r&&(r=Math.ceil(Yt(s*n))),r<-4)r=-4;else if(s>=7.99||r>3)return null;var u=Math.pow(2,r),c=t.h*u,d=t.w*u,h=o.eleTextBiggerThanMin(e,u);if(!this.isVisible(e,h))return null;var f,p=l.get(e,r);if(p&&p.invalidated&&(p.invalidated=!1,p.texture.invalidatedWidth-=p.width),p)return p;if(f=c<=25?25:c<=50?50:50*Math.ceil(c/50),c>1024||d>1024)return null;var v=i.getTextureQueue(f),g=v[v.length-2],y=function(){return i.recycleTexture(f,d)||i.addTexture(f,d)};g||(g=v[v.length-1]),g||(g=y()),g.width-g.usedWidthr;S--)C=i.getElement(e,t,n,S,ld.downscale);P()}else{var B;if(!x&&!w&&!E)for(var D=r-1;D>=-4;D--){var _=l.get(e,D);if(_){B=_;break}}if(b(B))return i.queueElement(e,r),B;g.context.translate(g.usedWidth,0),g.context.scale(u,u),this.drawElement(g.context,e,t,h,!1),g.context.scale(1/u,1/u),g.context.translate(-g.usedWidth,0)}return p={x:g.usedWidth,texture:g,level:r,scale:u,width:d,height:c,scaledLabelShown:h},g.usedWidth+=Math.ceil(d+8),g.eleCaches.push(p),l.set(e,r,p),i.checkTextureFullness(g),p},dd.invalidateElements=function(e){for(var t=0;t=.2*e.width&&this.retireTexture(e)},dd.checkTextureFullness=function(e){var t=this.getTextureQueue(e.height);e.usedWidth/e.width>.8&&e.fullnessChecks>=10?ut(t,e):e.fullnessChecks++},dd.retireTexture=function(e){var t=e.height,n=this.getTextureQueue(t),r=this.lookup;ut(n,e),e.retired=!0;for(var a=e.eleCaches,i=0;i=t)return i.retired=!1,i.usedWidth=0,i.invalidatedWidth=0,i.fullnessChecks=0,ct(i.eleCaches),i.context.setTransform(1,0,0,1,0,0),i.context.clearRect(0,0,i.width,i.height),ut(r,i),n.push(i),i}},dd.queueElement=function(e,t){var n=this.getElementQueue(),r=this.getElementKeyToQueue(),a=this.getKey(e),i=r[a];if(i)i.level=Math.max(i.level,t),i.eles.merge(e),i.reqs++,n.updateItem(i);else{var o={eles:e.spawn().merge(e),level:t,reqs:1,key:a};n.push(o),r[a]=o}},dd.dequeue=function(e){for(var t=this,n=t.getElementQueue(),r=t.getElementKeyToQueue(),a=[],i=t.lookup,o=0;o<1&&n.size()>0;o++){var s=n.pop(),l=s.key,u=s.eles[0],c=i.hasCache(u,s.level);if(r[l]=null,!c){a.push(s);var d=t.getBoundingBox(u);t.getElement(u,d,e,s.level,ld.dequeue)}}return a},dd.removeFromQueue=function(e){var t=this.getElementQueue(),n=this.getElementKeyToQueue(),r=this.getKey(e),a=n[r];null!=a&&(1===a.eles.length?(a.reqs=Ze,t.updateItem(a),t.pop(),n[r]=null):a.eles.unmerge(e))},dd.onDequeue=function(e){this.onDequeues.push(e)},dd.offDequeue=function(e){ut(this.onDequeues,e)},dd.setupDequeueing=id({deqRedrawThreshold:100,deqCost:.15,deqAvgCost:.1,deqNoDrawCost:.9,deqFastCost:.9,deq:function(e,t,n){return e.dequeue(t,n)},onDeqd:function(e,t){for(var n=0;n=3.99||n>2)return null;r.validateLayersElesOrdering(n,e);var o,s,l=r.layersByLevel,u=Math.pow(2,n),c=l[n]=l[n]||[];if(r.levelIsComplete(n,e))return c;!function(){var t=function(t){if(r.validateLayersElesOrdering(t,e),r.levelIsComplete(t,e))return s=l[t],!0},a=function(e){if(!s)for(var r=n+e;-4<=r&&r<=2&&!t(r);r+=e);};a(1),a(-1);for(var i=c.length-1;i>=0;i--){var o=c[i];o.invalid&&ut(c,o)}}();var d=function(t){var a=(t=t||{}).after;!function(){if(!o){o=Qt();for(var t=0;t32767||s>32767)return null;if(i*s>16e6)return null;var l=r.makeLayer(o,n);if(null!=a){var d=c.indexOf(a)+1;c.splice(d,0,l)}else(void 0===t.insert||t.insert)&&c.unshift(l);return l};if(r.skipping&&!i)return null;for(var h,f,p=null,v=e.length/1,g=!i,y=0;y=v||(h=p.bb,f=m.boundingBox(),!an(h,f.x1,f.y1)||!an(h,f.x2,f.y2)))&&!(p=d({insert:!0,after:p})))return null;s||g?r.queueLayer(p,m):r.drawEleInLayer(p,m,n,t),p.eles.push(m),x[n]=p}}return s||(g?null:c)},fd.getEleLevelForLayerLevel=function(e,t){return e},fd.drawEleInLayer=function(e,t,n,r){var a=this.renderer,i=e.context,o=t.boundingBox();0!==o.w&&0!==o.h&&t.visible()&&(n=this.getEleLevelForLayerLevel(n,r),a.setImgSmoothing(i,!1),a.drawCachedElement(i,t,null,null,n,true),a.setImgSmoothing(i,!0))},fd.levelIsComplete=function(e,t){var n=this.layersByLevel[e];if(!n||0===n.length)return!1;for(var r=0,a=0;a0)return!1;if(i.invalid)return!1;r+=i.eles.length}return r===t.length},fd.validateLayersElesOrdering=function(e,t){var n=this.layersByLevel[e];if(n)for(var r=0;r0){e=!0;break}}return e},fd.invalidateElements=function(e){var t=this;0!==e.length&&(t.lastInvalidationTime=Ne(),0!==e.length&&t.haveLayers()&&t.updateElementsInLayers(e,(function(e,n,r){t.invalidateLayer(e)})))},fd.invalidateLayer=function(e){if(this.lastInvalidationTime=Ne(),!e.invalid){var t=e.level,n=e.eles,r=this.layersByLevel[t];ut(r,e),e.elesQueue=[],e.invalid=!0,e.replacement&&(e.replacement.invalid=!0);for(var a=0;a3&&void 0!==arguments[3])||arguments[3],a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],i=!(arguments.length>5&&void 0!==arguments[5])||arguments[5],o=this,s=t._private.rscratch;if((!i||t.visible())&&!s.badLine&&null!=s.allpts&&!isNaN(s.allpts[0])){var l;n&&(l=n,e.translate(-l.x1,-l.y1));var u=i?t.pstyle("opacity").value:1,c=i?t.pstyle("line-opacity").value:1,d=t.pstyle("curve-style").value,h=t.pstyle("line-style").value,f=t.pstyle("width").pfValue,p=t.pstyle("line-cap").value,v=t.pstyle("line-outline-width").value,g=t.pstyle("line-outline-color").value,y=u*c,m=u*c,b=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:y;"straight-triangle"===d?(o.eleStrokeStyle(e,t,n),o.drawEdgeTrianglePath(t,e,s.allpts)):(e.lineWidth=f,e.lineCap=p,o.eleStrokeStyle(e,t,n),o.drawEdgePath(t,e,s.allpts,h),e.lineCap="butt")},x=function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:m;o.drawArrowheads(e,t,n)};if(e.lineJoin="round","yes"===t.pstyle("ghost").value){var w=t.pstyle("ghost-offset-x").pfValue,E=t.pstyle("ghost-offset-y").pfValue,k=t.pstyle("ghost-opacity").value,T=y*k;e.translate(w,E),b(T),x(T),e.translate(-w,-E)}else!function(){var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:y;e.lineWidth=f+v,e.lineCap=p,v>0?(o.colorStrokeStyle(e,g[0],g[1],g[2],n),"straight-triangle"===d?o.drawEdgeTrianglePath(t,e,s.allpts):(o.drawEdgePath(t,e,s.allpts,h),e.lineCap="butt")):e.lineCap="butt"}();a&&o.drawEdgeUnderlay(e,t),b(),x(),a&&o.drawEdgeOverlay(e,t),o.drawElementText(e,t,null,r),n&&e.translate(l.x1,l.y1)}}},Ad=function(e){if(!["overlay","underlay"].includes(e))throw new Error("Invalid state");return function(t,n){if(n.visible()){var r=n.pstyle("".concat(e,"-opacity")).value;if(0!==r){var a=this,i=a.usePaths(),o=n._private.rscratch,s=2*n.pstyle("".concat(e,"-padding")).pfValue,l=n.pstyle("".concat(e,"-color")).value;t.lineWidth=s,"self"!==o.edgeType||i?t.lineCap="round":t.lineCap="butt",a.colorStrokeStyle(t,l[0],l[1],l[2],r),a.drawEdgePath(n,t,o.allpts,"solid")}}}};_d.drawEdgeOverlay=Ad("overlay"),_d.drawEdgeUnderlay=Ad("underlay"),_d.drawEdgePath=function(e,t,n,a){var i,o=e._private.rscratch,s=t,l=!1,u=this.usePaths(),c=e.pstyle("line-dash-pattern").pfValue,d=e.pstyle("line-dash-offset").pfValue;if(u){var h=n.join("$");o.pathCacheKey&&o.pathCacheKey===h?(i=t=o.pathCache,l=!0):(i=t=new Path2D,o.pathCacheKey=h,o.pathCache=i)}if(s.setLineDash)switch(a){case"dotted":s.setLineDash([1,1]);break;case"dashed":s.setLineDash(c),s.lineDashOffset=d;break;case"solid":s.setLineDash([])}if(!l&&!o.badLine)switch(t.beginPath&&t.beginPath(),t.moveTo(n[0],n[1]),o.edgeType){case"bezier":case"self":case"compound":case"multibezier":for(var f=2;f+35&&void 0!==arguments[5]?arguments[5]:5,o=arguments.length>6?arguments[6]:void 0;e.beginPath(),e.moveTo(t+i,n),e.lineTo(t+r-i,n),e.quadraticCurveTo(t+r,n,t+r,n+i),e.lineTo(t+r,n+a-i),e.quadraticCurveTo(t+r,n+a,t+r-i,n+a),e.lineTo(t+i,n+a),e.quadraticCurveTo(t,n+a,t,n+a-i),e.lineTo(t,n+i),e.quadraticCurveTo(t,n,t+i,n),e.closePath(),o?e.stroke():e.fill()}Rd.eleTextBiggerThanMin=function(e,t){if(!t){var n=e.cy().zoom(),r=this.getPixelRatio(),a=Math.ceil(Yt(n*r));t=Math.pow(2,a)}return!(e.pstyle("font-size").pfValue*t5&&void 0!==arguments[5])||arguments[5],o=this;if(null==r){if(i&&!o.eleTextBiggerThanMin(t))return}else if(!1===r)return;if(t.isNode()){var s=t.pstyle("label");if(!s||!s.value)return;var l=o.getLabelJustification(t);e.textAlign=l,e.textBaseline="bottom"}else{var u=t.element()._private.rscratch.badLine,c=t.pstyle("label"),d=t.pstyle("source-label"),h=t.pstyle("target-label");if(u||(!c||!c.value)&&(!d||!d.value)&&(!h||!h.value))return;e.textAlign="center",e.textBaseline="bottom"}var f,p=!n;n&&(f=n,e.translate(-f.x1,-f.y1)),null==a?(o.drawText(e,t,null,p,i),t.isEdge()&&(o.drawText(e,t,"source",p,i),o.drawText(e,t,"target",p,i))):o.drawText(e,t,a,p,i),n&&e.translate(f.x1,f.y1)},Rd.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var n=0;n2&&void 0!==arguments[2])||arguments[2],r=t.pstyle("font-style").strValue,a=t.pstyle("font-size").pfValue+"px",i=t.pstyle("font-family").strValue,o=t.pstyle("font-weight").strValue,s=n?t.effectiveOpacity()*t.pstyle("text-opacity").value:1,l=t.pstyle("text-outline-opacity").value*s,u=t.pstyle("color").value,c=t.pstyle("text-outline-color").value;e.font=r+" "+o+" "+a+" "+i,e.lineJoin="round",this.colorFillStyle(e,u[0],u[1],u[2],s),this.colorStrokeStyle(e,c[0],c[1],c[2],l)},Rd.getTextAngle=function(e,t){var n,r=e._private.rscratch,a=t?t+"-":"",i=e.pstyle(a+"text-rotation");if("autorotate"===i.strValue){var o=dt(r,"labelAngle",t);n=e.isEdge()?o:0}else n="none"===i.strValue?0:i.pfValue;return n},Rd.drawText=function(e,t,n){var r=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],i=t._private.rscratch,o=a?t.effectiveOpacity():1;if(!a||0!==o&&0!==t.pstyle("text-opacity").value){"main"===n&&(n=null);var s,l,u=dt(i,"labelX",n),c=dt(i,"labelY",n),d=this.getLabelText(t,n);if(null!=d&&""!==d&&!isNaN(u)&&!isNaN(c)){this.setupTextStyle(e,t,a);var h,f=n?n+"-":"",p=dt(i,"labelWidth",n),v=dt(i,"labelHeight",n),g=t.pstyle(f+"text-margin-x").pfValue,y=t.pstyle(f+"text-margin-y").pfValue,m=t.isEdge(),b=t.pstyle("text-halign").value,x=t.pstyle("text-valign").value;switch(m&&(b="center",x="center"),u+=g,c+=y,0!==(h=r?this.getTextAngle(t,n):0)&&(s=u,l=c,e.translate(s,l),e.rotate(h),u=0,c=0),x){case"top":break;case"center":c+=v/2;break;case"bottom":c+=v}var w=t.pstyle("text-background-opacity").value,E=t.pstyle("text-border-opacity").value,k=t.pstyle("text-border-width").pfValue,T=t.pstyle("text-background-padding").pfValue,C=0===t.pstyle("text-background-shape").strValue.indexOf("round");if(w>0||k>0&&E>0){var P=u-T;switch(b){case"left":P-=p;break;case"center":P-=p/2}var S=c-v-T,B=p+2*T,D=v+2*T;if(w>0){var _=e.fillStyle,A=t.pstyle("text-background-color").value;e.fillStyle="rgba("+A[0]+","+A[1]+","+A[2]+","+w*o+")",C?Id(e,P,S,B,D,2):e.fillRect(P,S,B,D),e.fillStyle=_}if(k>0&&E>0){var M=e.strokeStyle,R=e.lineWidth,I=t.pstyle("text-border-color").value,N=t.pstyle("text-border-style").value;if(e.strokeStyle="rgba("+I[0]+","+I[1]+","+I[2]+","+E*o+")",e.lineWidth=k,e.setLineDash)switch(N){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"double":e.lineWidth=k/4,e.setLineDash([]);break;case"solid":e.setLineDash([])}if(C?Id(e,P,S,B,D,2,"stroke"):e.strokeRect(P,S,B,D),"double"===N){var L=k/2;C?Id(e,P+L,S+L,B-2*L,D-2*L,2,"stroke"):e.strokeRect(P+L,S+L,B-2*L,D-2*L)}e.setLineDash&&e.setLineDash([]),e.lineWidth=R,e.strokeStyle=M}}var z=2*t.pstyle("text-outline-width").pfValue;if(z>0&&(e.lineWidth=z),"wrap"===t.pstyle("text-wrap").value){var O=dt(i,"labelWrapCachedLines",n),V=dt(i,"labelLineHeight",n),F=p/2,j=this.getLabelJustification(t);switch("auto"===j||("left"===b?"left"===j?u+=-p:"center"===j&&(u+=-F):"center"===b?"left"===j?u+=-F:"right"===j&&(u+=F):"right"===b&&("center"===j?u+=F:"right"===j&&(u+=p))),x){case"top":case"center":case"bottom":c-=(O.length-1)*V}for(var X=0;X0&&e.strokeText(O[X],u,c),e.fillText(O[X],u,c),c+=V}else z>0&&e.strokeText(d,u,c),e.fillText(d,u,c);0!==h&&(e.rotate(-h),e.translate(-s,-l))}}};var Nd={drawNode:function(e,t,n){var r,a,i=!(arguments.length>3&&void 0!==arguments[3])||arguments[3],o=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],s=!(arguments.length>5&&void 0!==arguments[5])||arguments[5],l=this,u=t._private,c=u.rscratch,d=t.position();if(G(d.x)&&G(d.y)&&(!s||t.visible())){var h,f,p=s?t.effectiveOpacity():1,v=l.usePaths(),g=!1,y=t.padding();r=t.width()+2*y,a=t.height()+2*y,n&&(f=n,e.translate(-f.x1,-f.y1));for(var m=t.pstyle("background-image").value,b=new Array(m.length),x=new Array(m.length),w=0,E=0;E0&&void 0!==arguments[0]?arguments[0]:S;l.eleFillStyle(e,t,n)},q=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:N;l.colorStrokeStyle(e,B[0],B[1],B[2],t)},Y=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:V;l.colorStrokeStyle(e,z[0],z[1],z[2],t)},W=function(e,t,n,r){var a,i=l.nodePathCache=l.nodePathCache||[],o=We("polygon"===n?n+","+r.join(","):n,""+t,""+e,""+j),s=i[o],u=!1;return null!=s?(a=s,u=!0,c.pathCache=a):(a=new Path2D,i[o]=c.pathCache=a),{path:a,cacheHit:u}},U=t.pstyle("shape").strValue,H=t.pstyle("shape-polygon-points").pfValue;if(v){e.translate(d.x,d.y);var K=W(r,a,U,H);h=K.path,g=K.cacheHit}var Z=function(){if(!g){var n=d;v&&(n={x:0,y:0}),l.nodeShapes[l.getNodeShape(t)].draw(h||e,n.x,n.y,r,a,j,c)}v?e.fill(h):e.fill()},$=function(){for(var n=arguments.length>0&&void 0!==arguments[0]?arguments[0]:p,r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1],a=u.backgrounding,i=0,o=0;o0&&void 0!==arguments[0]&&arguments[0],i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:p;l.hasPie(t)&&(l.drawPie(e,t,i),n&&(v||l.nodeShapes[l.getNodeShape(t)].draw(e,d.x,d.y,r,a,j,c)))},J=function(){var n=arguments.length>0&&void 0!==arguments[0]&&arguments[0],i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:p;l.hasStripe(t)&&(e.save(),v?e.clip(c.pathCache):(l.nodeShapes[l.getNodeShape(t)].draw(e,d.x,d.y,r,a,j,c),e.clip()),l.drawStripe(e,t,i),e.restore(),n&&(v||l.nodeShapes[l.getNodeShape(t)].draw(e,d.x,d.y,r,a,j,c)))},ee=function(){var t=(C>0?C:-C)*(arguments.length>0&&void 0!==arguments[0]?arguments[0]:p),n=C>0?0:255;0!==C&&(l.colorFillStyle(e,n,n,n,t),v?e.fill(h):e.fill())},te=function(){if(P>0){if(e.lineWidth=P,e.lineCap=A,e.lineJoin=_,e.setLineDash)switch(D){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash(R),e.lineDashOffset=I;break;case"solid":case"double":e.setLineDash([])}if("center"!==M){if(e.save(),e.lineWidth*=2,"inside"===M)v?e.clip(h):e.clip();else{var t=new Path2D;t.rect(-r/2-P,-a/2-P,r+2*P,a+2*P),t.addPath(h),e.clip(t,"evenodd")}v?e.stroke(h):e.stroke(),e.restore()}else v?e.stroke(h):e.stroke();if("double"===D){e.lineWidth=P/3;var n=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",v?e.stroke(h):e.stroke(),e.globalCompositeOperation=n}e.setLineDash&&e.setLineDash([])}},ne=function(){if(L>0){if(e.lineWidth=L,e.lineCap="butt",e.setLineDash)switch(O){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"solid":case"double":e.setLineDash([])}var n=d;v&&(n={x:0,y:0});var i=l.getNodeShape(t),o=P;"inside"===M&&(o=0),"outside"===M&&(o*=2);var s,u=(r+o+(L+F))/r,c=(a+o+(L+F))/a,h=r*u,f=a*c,p=l.nodeShapes[i].points;if(v)s=W(h,f,i,p).path;if("ellipse"===i)l.drawEllipsePath(s||e,n.x,n.y,h,f);else if(["round-diamond","round-heptagon","round-hexagon","round-octagon","round-pentagon","round-polygon","round-triangle","round-tag"].includes(i)){var g=0,y=0,m=0;"round-diamond"===i?g=1.4*(o+F+L):"round-heptagon"===i?(g=1.075*(o+F+L),m=-(o/2+F+L)/35):"round-hexagon"===i?g=1.12*(o+F+L):"round-pentagon"===i?(g=1.13*(o+F+L),m=-(o/2+F+L)/15):"round-tag"===i?(g=1.12*(o+F+L),y=.07*(o/2+L+F)):"round-triangle"===i&&(g=(o+F+L)*(Math.PI/2),m=-(o+F/2+L)/Math.PI),0!==g&&(h=r*(u=(r+g)/r),["round-hexagon","round-tag"].includes(i)||(f=a*(c=(a+g)/a)));for(var b=h/2,x=f/2,w=(j="auto"===j?Bn(h,f):j)+(o+L+F)/2,E=new Array(p.length/2),k=new Array(p.length/2),T=0;T0){if(r=r||n.position(),null==a||null==i){var d=n.padding();a=n.width()+2*d,i=n.height()+2*d}this.colorFillStyle(t,l[0],l[1],l[2],s),this.nodeShapes[u].draw(t,r.x,r.y,a+2*o,i+2*o,c),t.fill()}}}};Nd.drawNodeOverlay=Ld("overlay"),Nd.drawNodeUnderlay=Ld("underlay"),Nd.hasPie=function(e){return(e=e[0])._private.hasPie},Nd.hasStripe=function(e){return(e=e[0])._private.hasStripe},Nd.drawPie=function(e,t,n,r){t=t[0],r=r||t.position();var a,i=t.cy().style(),o=t.pstyle("pie-size"),s=t.pstyle("pie-hole"),l=t.pstyle("pie-start-angle").pfValue,u=r.x,c=r.y,d=t.width(),h=t.height(),f=Math.min(d,h)/2,p=0;if(this.usePaths()&&(u=0,c=0),"%"===o.units?f*=o.pfValue:void 0!==o.pfValue&&(f=o.pfValue/2),"%"===s.units?a=f*s.pfValue:void 0!==s.pfValue&&(a=s.pfValue/2),!(a>=f))for(var v=1;v<=i.pieBackgroundN;v++){var g=t.pstyle("pie-"+v+"-background-size").value,y=t.pstyle("pie-"+v+"-background-color").value,m=t.pstyle("pie-"+v+"-background-opacity").value*n,b=g/100;b+p>1&&(b=1-p);var x=1.5*Math.PI+2*Math.PI*p,w=(x+=l)+2*Math.PI*b;0===g||p>=1||p+b>1||(0===a?(e.beginPath(),e.moveTo(u,c),e.arc(u,c,f,x,w),e.closePath()):(e.beginPath(),e.arc(u,c,f,x,w),e.arc(u,c,a,w,x,!0),e.closePath()),this.colorFillStyle(e,y[0],y[1],y[2],m),e.fill(),p+=b)}},Nd.drawStripe=function(e,t,n,r){t=t[0],r=r||t.position();var a=t.cy().style(),i=r.x,o=r.y,s=t.width(),l=t.height(),u=0,c=this.usePaths();e.save();var d=t.pstyle("stripe-direction").value,h=t.pstyle("stripe-size");switch(d){case"vertical":break;case"righward":e.rotate(-Math.PI/2)}var f=s,p=l;"%"===h.units?(f*=h.pfValue,p*=h.pfValue):void 0!==h.pfValue&&(f=h.pfValue,p=h.pfValue),c&&(i=0,o=0),o-=f/2,i-=p/2;for(var v=1;v<=a.stripeBackgroundN;v++){var g=t.pstyle("stripe-"+v+"-background-size").value,y=t.pstyle("stripe-"+v+"-background-color").value,m=t.pstyle("stripe-"+v+"-background-opacity").value*n,b=g/100;b+u>1&&(b=1-u),0===g||u>=1||u+b>1||(e.beginPath(),e.rect(i,o+p*u,f,p*b),e.closePath(),this.colorFillStyle(e,y[0],y[1],y[2],m),e.fill(),u+=b)}e.restore()};var zd,Od={};function Vd(e,t,n){var r=e.createShader(t);if(e.shaderSource(r,n),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS))throw new Error(e.getShaderInfoLog(r));return r}function Fd(e,t,n){void 0===n&&(n=t);var r=e.makeOffscreenCanvas(t,n),a=r.context=r.getContext("2d");return r.clear=function(){return a.clearRect(0,0,r.width,r.height)},r.clear(),r}function jd(e){var t=e.pixelRatio,n=e.cy.zoom(),r=e.cy.pan();return{zoom:n*t,pan:{x:r.x*t,y:r.y*t}}}function Xd(e){return"solid"===e.pstyle("background-fill").value&&("none"===e.pstyle("background-image").strValue&&(0===e.pstyle("border-width").value||(0===e.pstyle("border-opacity").value||"solid"===e.pstyle("border-style").value)))}function qd(e,t){if(e.length!==t.length)return!1;for(var n=0;n>8&255)/255,n[2]=(e>>16&255)/255,n[3]=(e>>24&255)/255,n}function Ud(e){return e[0]+(e[1]<<8)+(e[2]<<16)+(e[3]<<24)}function Hd(e,t){switch(t){case"float":return[1,e.FLOAT,4];case"vec2":return[2,e.FLOAT,4];case"vec3":return[3,e.FLOAT,4];case"vec4":return[4,e.FLOAT,4];case"int":return[1,e.INT,4];case"ivec2":return[2,e.INT,4]}}function Kd(e,t,n){switch(t){case e.FLOAT:return new Float32Array(n);case e.INT:return new Int32Array(n)}}function Gd(e,t,n,r,a,i){switch(t){case e.FLOAT:return new Float32Array(n.buffer,i*r,a);case e.INT:return new Int32Array(n.buffer,i*r,a)}}function Zd(e,t,n,r){var a=i(Hd(e,n),3),o=a[0],s=a[1],l=a[2],u=Kd(e,s,t*o),c=o*l,d=e.createBuffer();e.bindBuffer(e.ARRAY_BUFFER,d),e.bufferData(e.ARRAY_BUFFER,t*c,e.DYNAMIC_DRAW),e.enableVertexAttribArray(r),s===e.FLOAT?e.vertexAttribPointer(r,o,s,!1,c,0):s===e.INT&&e.vertexAttribIPointer(r,o,s,c,0),e.vertexAttribDivisor(r,1),e.bindBuffer(e.ARRAY_BUFFER,null);for(var h=new Array(t),f=0;ft.minMbLowQualFrames&&(t.motionBlurPxRatio=t.mbPxRBlurry)),t.clearingMotionBlur&&(t.motionBlurPxRatio=1),t.textureDrawLastFrame&&!d&&(c[t.NODE]=!0,c[t.SELECT_BOX]=!0);var m=n.style(),b=n.zoom(),x=void 0!==o?o:b,w=n.pan(),E={x:w.x,y:w.y},k={zoom:b,pan:{x:w.x,y:w.y}},T=t.prevViewport;void 0===T||k.zoom!==T.zoom||k.pan.x!==T.pan.x||k.pan.y!==T.pan.y||v&&!p||(t.motionBlurPxRatio=1),s&&(E=s),x*=l,E.x*=l,E.y*=l;var C=t.getCachedZSortedEles();function P(e,n,r,a,i){var o=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",t.colorFillStyle(e,255,255,255,t.motionBlurTransparency),e.fillRect(n,r,a,i),e.globalCompositeOperation=o}function S(e,n){var i,l,c,d;t.clearingMotionBlur||e!==u.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]&&e!==u.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG]?(i=E,l=x,c=t.canvasWidth,d=t.canvasHeight):(i={x:w.x*f,y:w.y*f},l=b*f,c=t.canvasWidth*f,d=t.canvasHeight*f),e.setTransform(1,0,0,1,0,0),"motionBlur"===n?P(e,0,0,c,d):r||void 0!==n&&!n||e.clearRect(0,0,c,d),a||(e.translate(i.x,i.y),e.scale(l,l)),s&&e.translate(s.x,s.y),o&&e.scale(o,o)}if(d||(t.textureDrawLastFrame=!1),d){if(t.textureDrawLastFrame=!0,!t.textureCache){t.textureCache={},t.textureCache.bb=n.mutableElements().boundingBox(),t.textureCache.texture=t.data.bufferCanvases[t.TEXTURE_BUFFER];var B=t.data.bufferContexts[t.TEXTURE_BUFFER];B.setTransform(1,0,0,1,0,0),B.clearRect(0,0,t.canvasWidth*t.textureMult,t.canvasHeight*t.textureMult),t.render({forcedContext:B,drawOnlyNodeLayer:!0,forcedPxRatio:l*t.textureMult}),(k=t.textureCache.viewport={zoom:n.zoom(),pan:n.pan(),width:t.canvasWidth,height:t.canvasHeight}).mpan={x:(0-k.pan.x)/k.zoom,y:(0-k.pan.y)/k.zoom}}c[t.DRAG]=!1,c[t.NODE]=!1;var D=u.contexts[t.NODE],_=t.textureCache.texture;k=t.textureCache.viewport;D.setTransform(1,0,0,1,0,0),h?P(D,0,0,k.width,k.height):D.clearRect(0,0,k.width,k.height);var A=m.core("outside-texture-bg-color").value,M=m.core("outside-texture-bg-opacity").value;t.colorFillStyle(D,A[0],A[1],A[2],M),D.fillRect(0,0,k.width,k.height);b=n.zoom();S(D,!1),D.clearRect(k.mpan.x,k.mpan.y,k.width/k.zoom/l,k.height/k.zoom/l),D.drawImage(_,k.mpan.x,k.mpan.y,k.width/k.zoom/l,k.height/k.zoom/l)}else t.textureOnViewport&&!r&&(t.textureCache=null);var R=n.extent(),I=t.pinching||t.hoverData.dragging||t.swipePanning||t.data.wheelZooming||t.hoverData.draggingEles||t.cy.animated(),N=t.hideEdgesOnViewport&&I,L=[];if(L[t.NODE]=!c[t.NODE]&&h&&!t.clearedForMotionBlur[t.NODE]||t.clearingMotionBlur,L[t.NODE]&&(t.clearedForMotionBlur[t.NODE]=!0),L[t.DRAG]=!c[t.DRAG]&&h&&!t.clearedForMotionBlur[t.DRAG]||t.clearingMotionBlur,L[t.DRAG]&&(t.clearedForMotionBlur[t.DRAG]=!0),c[t.NODE]||a||i||L[t.NODE]){var z=h&&!L[t.NODE]&&1!==f;S(D=r||(z?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_NODE]:u.contexts[t.NODE]),h&&!z?"motionBlur":void 0),N?t.drawCachedNodes(D,C.nondrag,l,R):t.drawLayeredElements(D,C.nondrag,l,R),t.debug&&t.drawDebugPoints(D,C.nondrag),a||h||(c[t.NODE]=!1)}if(!i&&(c[t.DRAG]||a||L[t.DRAG])){z=h&&!L[t.DRAG]&&1!==f;S(D=r||(z?t.data.bufferContexts[t.MOTIONBLUR_BUFFER_DRAG]:u.contexts[t.DRAG]),h&&!z?"motionBlur":void 0),N?t.drawCachedNodes(D,C.drag,l,R):t.drawCachedElements(D,C.drag,l,R),t.debug&&t.drawDebugPoints(D,C.drag),a||h||(c[t.DRAG]=!1)}if(this.drawSelectionRectangle(e,S),h&&1!==f){var O=u.contexts[t.NODE],V=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE],F=u.contexts[t.DRAG],j=t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG],X=function(e,n,r){e.setTransform(1,0,0,1,0,0),r||!y?e.clearRect(0,0,t.canvasWidth,t.canvasHeight):P(e,0,0,t.canvasWidth,t.canvasHeight);var a=f;e.drawImage(n,0,0,t.canvasWidth*a,t.canvasHeight*a,0,0,t.canvasWidth,t.canvasHeight)};(c[t.NODE]||L[t.NODE])&&(X(O,V,L[t.NODE]),c[t.NODE]=!1),(c[t.DRAG]||L[t.DRAG])&&(X(F,j,L[t.DRAG]),c[t.DRAG]=!1)}t.prevViewport=k,t.clearingMotionBlur&&(t.clearingMotionBlur=!1,t.motionBlurCleared=!0,t.motionBlur=!0),h&&(t.motionBlurTimeout=setTimeout((function(){t.motionBlurTimeout=null,t.clearedForMotionBlur[t.NODE]=!1,t.clearedForMotionBlur[t.DRAG]=!1,t.motionBlur=!1,t.clearingMotionBlur=!d,t.mbFrames=0,c[t.NODE]=!0,c[t.DRAG]=!0,t.redraw()}),100)),r||n.emit("render")},Od.drawSelectionRectangle=function(e,t){var n=this,r=n.cy,a=n.data,i=r.style(),o=e.drawOnlyNodeLayer,s=e.drawAllLayers,l=a.canvasNeedsRedraw,u=e.forcedContext;if(n.showFps||!o&&l[n.SELECT_BOX]&&!s){var c=u||a.contexts[n.SELECT_BOX];if(t(c),1==n.selection[4]&&(n.hoverData.selecting||n.touchData.selecting)){var d=n.cy.zoom(),h=i.core("selection-box-border-width").value/d;c.lineWidth=h,c.fillStyle="rgba("+i.core("selection-box-color").value[0]+","+i.core("selection-box-color").value[1]+","+i.core("selection-box-color").value[2]+","+i.core("selection-box-opacity").value+")",c.fillRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]),h>0&&(c.strokeStyle="rgba("+i.core("selection-box-border-color").value[0]+","+i.core("selection-box-border-color").value[1]+","+i.core("selection-box-border-color").value[2]+","+i.core("selection-box-opacity").value+")",c.strokeRect(n.selection[0],n.selection[1],n.selection[2]-n.selection[0],n.selection[3]-n.selection[1]))}if(a.bgActivePosistion&&!n.hoverData.selecting){d=n.cy.zoom();var f=a.bgActivePosistion;c.fillStyle="rgba("+i.core("active-bg-color").value[0]+","+i.core("active-bg-color").value[1]+","+i.core("active-bg-color").value[2]+","+i.core("active-bg-opacity").value+")",c.beginPath(),c.arc(f.x,f.y,i.core("active-bg-size").pfValue/d,0,2*Math.PI),c.fill()}var p=n.lastRedrawTime;if(n.showFps&&p){p=Math.round(p);var v=Math.round(1e3/p),g="1 frame = "+p+" ms = "+v+" fps";if(c.setTransform(1,0,0,1,0,0),c.fillStyle="rgba(255, 0, 0, 0.75)",c.strokeStyle="rgba(255, 0, 0, 0.75)",c.font="30px Arial",!zd){var y=c.measureText(g);zd=y.actualBoundingBoxAscent}c.fillText(g,0,zd);c.strokeRect(0,zd+10,250,20),c.fillRect(0,zd+10,250*Math.min(v/60,1),20)}s||(l[n.SELECT_BOX]=!1)}};var $d="undefined"!=typeof Float32Array?Float32Array:Array;function Qd(){var e=new $d(9);return $d!=Float32Array&&(e[1]=0,e[2]=0,e[3]=0,e[5]=0,e[6]=0,e[7]=0),e[0]=1,e[4]=1,e[8]=1,e}function Jd(e){return e[0]=1,e[1]=0,e[2]=0,e[3]=0,e[4]=1,e[5]=0,e[6]=0,e[7]=0,e[8]=1,e}function eh(e,t,n){var r=t[0],a=t[1],i=t[2],o=t[3],s=t[4],l=t[5],u=t[6],c=t[7],d=t[8],h=n[0],f=n[1];return e[0]=r,e[1]=a,e[2]=i,e[3]=o,e[4]=s,e[5]=l,e[6]=h*r+f*o+u,e[7]=h*a+f*s+c,e[8]=h*i+f*l+d,e}function th(e,t,n){var r=t[0],a=t[1],i=t[2],o=t[3],s=t[4],l=t[5],u=t[6],c=t[7],d=t[8],h=Math.sin(n),f=Math.cos(n);return e[0]=f*r+h*o,e[1]=f*a+h*s,e[2]=f*i+h*l,e[3]=f*o-h*r,e[4]=f*s-h*a,e[5]=f*l-h*i,e[6]=u,e[7]=c,e[8]=d,e}function nh(e,t,n){var r=n[0],a=n[1];return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=a*t[3],e[4]=a*t[4],e[5]=a*t[5],e[6]=t[6],e[7]=t[7],e[8]=t[8],e}Math.hypot||(Math.hypot=function(){for(var e=0,t=arguments.length;t--;)e+=arguments[t]*arguments[t];return Math.sqrt(e)});var rh=function(){return n((function e(n,r,a,i){t(this,e),this.debugID=Math.floor(1e4*Math.random()),this.r=n,this.texSize=r,this.texRows=a,this.texHeight=Math.floor(r/a),this.enableWrapping=!0,this.locked=!1,this.texture=null,this.needsBuffer=!0,this.freePointer={x:0,row:0},this.keyToLocation=new Map,this.canvas=i(n,r,r),this.scratch=i(n,r,this.texHeight,"scratch")}),[{key:"lock",value:function(){this.locked=!0}},{key:"getKeys",value:function(){return new Set(this.keyToLocation.keys())}},{key:"getScale",value:function(e){var t=e.w,n=e.h,r=this.texHeight,a=this.texSize,i=r/n,o=t*i,s=n*i;return o>a&&(o=t*(i=a/t),s=n*i),{scale:i,texW:o,texH:s}}},{key:"draw",value:function(e,t,n){var r=this;if(this.locked)throw new Error("can't draw, atlas is locked");var a=this.texSize,i=this.texRows,o=this.texHeight,s=this.getScale(t),l=s.scale,u=s.texW,c=s.texH,d=function(e,r){if(n&&r){var a=r.context,i=e.x,s=e.row,u=i,c=o*s;a.save(),a.translate(u,c),a.scale(l,l),n(a,t),a.restore()}},h=[null,null],f=function(){d(r.freePointer,r.canvas),h[0]={x:r.freePointer.x,y:r.freePointer.row*o,w:u,h:c},h[1]={x:r.freePointer.x+u,y:r.freePointer.row*o,w:0,h:c},r.freePointer.x+=u,r.freePointer.x==a&&(r.freePointer.x=0,r.freePointer.row++)},p=function(){r.freePointer.x=0,r.freePointer.row++};if(this.freePointer.x+u<=a)f();else{if(this.freePointer.row>=i-1)return!1;this.freePointer.x===a?(p(),f()):this.enableWrapping?function(){var e=r.scratch,t=r.canvas;e.clear(),d({x:0,row:0},e);var n=a-r.freePointer.x,i=u-n,s=o,l=r.freePointer.x,f=r.freePointer.row*o,p=n;t.context.drawImage(e,0,0,p,s,l,f,p,s),h[0]={x:l,y:f,w:p,h:c};var v=n,g=(r.freePointer.row+1)*o,y=i;t&&t.context.drawImage(e,v,0,y,s,0,g,y,s),h[1]={x:0,y:g,w:y,h:c},r.freePointer.x=i,r.freePointer.row++}():(p(),f())}return this.keyToLocation.set(e,h),this.needsBuffer=!0,h}},{key:"getOffsets",value:function(e){return this.keyToLocation.get(e)}},{key:"isEmpty",value:function(){return 0===this.freePointer.x&&0===this.freePointer.row}},{key:"canFit",value:function(e){if(this.locked)return!1;var t=this.texSize,n=this.texRows,r=this.getScale(e).texW;return!(this.freePointer.x+r>t)||this.freePointer.row1&&void 0!==arguments[1]?arguments[1]:{},i=a.forceRedraw,o=void 0!==i&&i,s=a.filterEle,l=void 0===s?function(){return!0}:s,u=a.filterType,c=void 0===u?function(){return!0}:u,d=!1,h=!1,f=r(e);try{for(f.s();!(t=f.n()).done;){var p=t.value;if(l(p)){var v,g=r(this.renderTypes.values());try{var y=function(){var e=v.value,t=e.type;if(c(t)){var r=n.collections.get(e.collection),a=e.getKey(p),i=Array.isArray(a)?a:[a];if(o)i.forEach((function(e){return r.markKeyForGC(e)})),h=!0;else{var s=e.getID?e.getID(p):p.id(),l=n._key(t,s),u=n.typeAndIdToKey.get(l);void 0===u||qd(i,u)||(d=!0,n.typeAndIdToKey.delete(l),u.forEach((function(e){return r.markKeyForGC(e)})))}}};for(g.s();!(v=g.n()).done;)y()}catch(e){g.e(e)}finally{g.f()}}}}catch(e){f.e(e)}finally{f.f()}return h&&(this.gc(),d=!1),d}},{key:"gc",value:function(){var e,t=r(this.collections.values());try{for(t.s();!(e=t.n()).done;){e.value.gc()}}catch(e){t.e(e)}finally{t.f()}}},{key:"getOrCreateAtlas",value:function(e,t,n,r){var a=this.renderTypes.get(t),i=this.collections.get(a.collection),o=!1,s=i.draw(r,n,(function(t){a.drawClipped?(t.save(),t.beginPath(),t.rect(0,0,n.w,n.h),t.clip(),a.drawElement(t,e,n,!0,!0),t.restore()):a.drawElement(t,e,n,!0,!0),o=!0}));if(o){var l=a.getID?a.getID(e):e.id(),u=this._key(t,l);this.typeAndIdToKey.has(u)?this.typeAndIdToKey.get(u).push(r):this.typeAndIdToKey.set(u,[r])}return s}},{key:"getAtlasInfo",value:function(e,t){var n=this,r=this.renderTypes.get(t),a=r.getKey(e);return(Array.isArray(a)?a:[a]).map((function(a){var o=r.getBoundingBox(e,a),s=n.getOrCreateAtlas(e,t,o,a),l=i(s.getOffsets(a),2),u=l[0];return{atlas:s,tex:u,tex1:u,tex2:l[1],bb:o}}))}},{key:"getDebugInfo",value:function(){var e,t=[],n=r(this.collections);try{for(n.s();!(e=n.n()).done;){var a=i(e.value,2),o=a[0],s=a[1].getCounts(),l=s.keyCount,u=s.atlasCount;t.push({type:o,keyCount:l,atlasCount:u})}}catch(e){n.e(e)}finally{n.f()}return t}}])}(),oh=function(){return n((function e(n){t(this,e),this.globalOptions=n,this.atlasSize=n.webglTexSize,this.maxAtlasesPerBatch=n.webglTexPerBatch,this.batchAtlases=[]}),[{key:"getMaxAtlasesPerBatch",value:function(){return this.maxAtlasesPerBatch}},{key:"getAtlasSize",value:function(){return this.atlasSize}},{key:"getIndexArray",value:function(){return Array.from({length:this.maxAtlasesPerBatch},(function(e,t){return t}))}},{key:"startBatch",value:function(){this.batchAtlases=[]}},{key:"getAtlasCount",value:function(){return this.batchAtlases.length}},{key:"getAtlases",value:function(){return this.batchAtlases}},{key:"canAddToCurrentBatch",value:function(e){return this.batchAtlases.length!==this.maxAtlasesPerBatch||this.batchAtlases.includes(e)}},{key:"getAtlasIndexForBatch",value:function(e){var t=this.batchAtlases.indexOf(e);if(t<0){if(this.batchAtlases.length===this.maxAtlasesPerBatch)throw new Error("cannot add more atlases to batch");this.batchAtlases.push(e),t=this.batchAtlases.length-1}return t}}])}(),sh={SCREEN:{name:"screen",screen:!0},PICKING:{name:"picking",picking:!0}},lh=1,uh=2,ch=function(){return n((function e(n,r,a){t(this,e),this.r=n,this.gl=r,this.maxInstances=a.webglBatchSize,this.atlasSize=a.webglTexSize,this.bgColor=a.bgColor,this.debug=a.webglDebug,this.batchDebugInfo=[],a.enableWrapping=!0,a.createTextureCanvas=Fd,this.atlasManager=new ih(n,a),this.batchManager=new oh(a),this.simpleShapeOptions=new Map,this.program=this._createShaderProgram(sh.SCREEN),this.pickingProgram=this._createShaderProgram(sh.PICKING),this.vao=this._createVAO()}),[{key:"addAtlasCollection",value:function(e,t){this.atlasManager.addAtlasCollection(e,t)}},{key:"addTextureAtlasRenderType",value:function(e,t){this.atlasManager.addRenderType(e,t)}},{key:"addSimpleShapeRenderType",value:function(e,t){this.simpleShapeOptions.set(e,t)}},{key:"invalidate",value:function(e){var t=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).type,n=this.atlasManager;return t?n.invalidate(e,{filterType:function(e){return e===t},forceRedraw:!0}):n.invalidate(e)}},{key:"gc",value:function(){this.atlasManager.gc()}},{key:"_createShaderProgram",value:function(e){var t=this.gl,n="#version 300 es\n precision highp float;\n\n uniform mat3 uPanZoomMatrix;\n uniform int uAtlasSize;\n \n // instanced\n in vec2 aPosition; // a vertex from the unit square\n \n in mat3 aTransform; // used to transform verticies, eg into a bounding box\n in int aVertType; // the type of thing we are rendering\n\n // the z-index that is output when using picking mode\n in vec4 aIndex;\n \n // For textures\n in int aAtlasId; // which shader unit/atlas to use\n in vec4 aTex; // x/y/w/h of texture in atlas\n\n // for edges\n in vec4 aPointAPointB;\n in vec4 aPointCPointD;\n in vec2 aLineWidth; // also used for node border width\n\n // simple shapes\n in vec4 aCornerRadius; // for round-rectangle [top-right, bottom-right, top-left, bottom-left]\n in vec4 aColor; // also used for edges\n in vec4 aBorderColor; // aLineWidth is used for border width\n\n // output values passed to the fragment shader\n out vec2 vTexCoord;\n out vec4 vColor;\n out vec2 vPosition;\n // flat values are not interpolated\n flat out int vAtlasId; \n flat out int vVertType;\n flat out vec2 vTopRight;\n flat out vec2 vBotLeft;\n flat out vec4 vCornerRadius;\n flat out vec4 vBorderColor;\n flat out vec2 vBorderWidth;\n flat out vec4 vIndex;\n \n void main(void) {\n int vid = gl_VertexID;\n vec2 position = aPosition; // TODO make this a vec3, simplifies some code below\n\n if(aVertType == ".concat(0,") {\n float texX = aTex.x; // texture coordinates\n float texY = aTex.y;\n float texW = aTex.z;\n float texH = aTex.w;\n\n if(vid == 1 || vid == 2 || vid == 4) {\n texX += texW;\n }\n if(vid == 2 || vid == 4 || vid == 5) {\n texY += texH;\n }\n\n float d = float(uAtlasSize);\n vTexCoord = vec2(texX / d, texY / d); // tex coords must be between 0 and 1\n\n gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);\n }\n else if(aVertType == ").concat(4," || aVertType == ").concat(7," \n || aVertType == ").concat(5," || aVertType == ").concat(6,") { // simple shapes\n\n // the bounding box is needed by the fragment shader\n vBotLeft = (aTransform * vec3(0, 0, 1)).xy; // flat\n vTopRight = (aTransform * vec3(1, 1, 1)).xy; // flat\n vPosition = (aTransform * vec3(position, 1)).xy; // will be interpolated\n\n // calculations are done in the fragment shader, just pass these along\n vColor = aColor;\n vCornerRadius = aCornerRadius;\n vBorderColor = aBorderColor;\n vBorderWidth = aLineWidth;\n\n gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);\n }\n else if(aVertType == ").concat(1,") {\n vec2 source = aPointAPointB.xy;\n vec2 target = aPointAPointB.zw;\n\n // adjust the geometry so that the line is centered on the edge\n position.y = position.y - 0.5;\n\n // stretch the unit square into a long skinny rectangle\n vec2 xBasis = target - source;\n vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));\n vec2 point = source + xBasis * position.x + yBasis * aLineWidth[0] * position.y;\n\n gl_Position = vec4(uPanZoomMatrix * vec3(point, 1.0), 1.0);\n vColor = aColor;\n } \n else if(aVertType == ").concat(2,") {\n vec2 pointA = aPointAPointB.xy;\n vec2 pointB = aPointAPointB.zw;\n vec2 pointC = aPointCPointD.xy;\n vec2 pointD = aPointCPointD.zw;\n\n // adjust the geometry so that the line is centered on the edge\n position.y = position.y - 0.5;\n\n vec2 p0, p1, p2, pos;\n if(position.x == 0.0) { // The left side of the unit square\n p0 = pointA;\n p1 = pointB;\n p2 = pointC;\n pos = position;\n } else { // The right side of the unit square, use same approach but flip the geometry upside down\n p0 = pointD;\n p1 = pointC;\n p2 = pointB;\n pos = vec2(0.0, -position.y);\n }\n\n vec2 p01 = p1 - p0;\n vec2 p12 = p2 - p1;\n vec2 p21 = p1 - p2;\n\n // Find the normal vector.\n vec2 tangent = normalize(normalize(p12) + normalize(p01));\n vec2 normal = vec2(-tangent.y, tangent.x);\n\n // Find the vector perpendicular to p0 -> p1.\n vec2 p01Norm = normalize(vec2(-p01.y, p01.x));\n\n // Determine the bend direction.\n float sigma = sign(dot(p01 + p21, normal));\n float width = aLineWidth[0];\n\n if(sign(pos.y) == -sigma) {\n // This is an intersecting vertex. Adjust the position so that there's no overlap.\n vec2 point = 0.5 * width * normal * -sigma / dot(normal, p01Norm);\n gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0);\n } else {\n // This is a non-intersecting vertex. Treat it like a mitre join.\n vec2 point = 0.5 * width * normal * sigma * dot(normal, p01Norm);\n gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0);\n }\n\n vColor = aColor;\n } \n else if(aVertType == ").concat(3," && vid < 3) {\n // massage the first triangle into an edge arrow\n if(vid == 0)\n position = vec2(-0.15, -0.3);\n if(vid == 1)\n position = vec2( 0.0, 0.0);\n if(vid == 2)\n position = vec2( 0.15, -0.3);\n\n gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);\n vColor = aColor;\n }\n else {\n gl_Position = vec4(2.0, 0.0, 0.0, 1.0); // discard vertex by putting it outside webgl clip space\n }\n\n vAtlasId = aAtlasId;\n vVertType = aVertType;\n vIndex = aIndex;\n }\n "),r=this.batchManager.getIndexArray(),a="#version 300 es\n precision highp float;\n\n // declare texture unit for each texture atlas in the batch\n ".concat(r.map((function(e){return"uniform sampler2D uTexture".concat(e,";")})).join("\n\t"),"\n\n uniform vec4 uBGColor;\n uniform float uZoom;\n\n in vec2 vTexCoord;\n in vec4 vColor;\n in vec2 vPosition; // model coordinates\n\n flat in int vAtlasId;\n flat in vec4 vIndex;\n flat in int vVertType;\n flat in vec2 vTopRight;\n flat in vec2 vBotLeft;\n flat in vec4 vCornerRadius;\n flat in vec4 vBorderColor;\n flat in vec2 vBorderWidth;\n\n out vec4 outColor;\n\n ").concat("\n float circleSD(vec2 p, float r) {\n return distance(vec2(0), p) - r; // signed distance\n }\n","\n ").concat("\n float rectangleSD(vec2 p, vec2 b) {\n vec2 d = abs(p)-b;\n return distance(vec2(0),max(d,0.0)) + min(max(d.x,d.y),0.0);\n }\n","\n ").concat("\n float roundRectangleSD(vec2 p, vec2 b, vec4 cr) {\n cr.xy = (p.x > 0.0) ? cr.xy : cr.zw;\n cr.x = (p.y > 0.0) ? cr.x : cr.y;\n vec2 q = abs(p) - b + cr.x;\n return min(max(q.x, q.y), 0.0) + distance(vec2(0), max(q, 0.0)) - cr.x;\n }\n","\n ").concat("\n float ellipseSD(vec2 p, vec2 ab) {\n p = abs( p ); // symmetry\n\n // find root with Newton solver\n vec2 q = ab*(p-ab);\n float w = (q.x1.0) ? d : -d;\n }\n","\n\n vec4 blend(vec4 top, vec4 bot) { // blend colors with premultiplied alpha\n return vec4( \n top.rgb + (bot.rgb * (1.0 - top.a)),\n top.a + (bot.a * (1.0 - top.a)) \n );\n }\n\n vec4 distInterp(vec4 cA, vec4 cB, float d) { // interpolate color using Signed Distance\n // scale to the zoom level so that borders don't look blurry when zoomed in\n // note 1.5 is an aribitrary value chosen because it looks good\n return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d))); \n }\n\n void main(void) {\n if(vVertType == ").concat(0,") {\n // look up the texel from the texture unit\n ").concat(r.map((function(e){return"if(vAtlasId == ".concat(e,") outColor = texture(uTexture").concat(e,", vTexCoord);")})).join("\n\telse "),"\n } \n else if(vVertType == ").concat(3,") {\n // mimics how canvas renderer uses context.globalCompositeOperation = 'destination-out';\n outColor = blend(vColor, uBGColor);\n outColor.a = 1.0; // make opaque, masks out line under arrow\n }\n else if(vVertType == ").concat(4," && vBorderWidth == vec2(0.0)) { // simple rectangle with no border\n outColor = vColor; // unit square is already transformed to the rectangle, nothing else needs to be done\n }\n else if(vVertType == ").concat(4," || vVertType == ").concat(7," \n || vVertType == ").concat(5," || vVertType == ").concat(6,") { // use SDF\n\n float outerBorder = vBorderWidth[0];\n float innerBorder = vBorderWidth[1];\n float borderPadding = outerBorder * 2.0;\n float w = vTopRight.x - vBotLeft.x - borderPadding;\n float h = vTopRight.y - vBotLeft.y - borderPadding;\n vec2 b = vec2(w/2.0, h/2.0); // half width, half height\n vec2 p = vPosition - vec2(vTopRight.x - b[0] - outerBorder, vTopRight.y - b[1] - outerBorder); // translate to center\n\n float d; // signed distance\n if(vVertType == ").concat(4,") {\n d = rectangleSD(p, b);\n } else if(vVertType == ").concat(7," && w == h) {\n d = circleSD(p, b.x); // faster than ellipse\n } else if(vVertType == ").concat(7,") {\n d = ellipseSD(p, b);\n } else {\n d = roundRectangleSD(p, b, vCornerRadius.wzyx);\n }\n\n // use the distance to interpolate a color to smooth the edges of the shape, doesn't need multisampling\n // we must smooth colors inwards, because we can't change pixels outside the shape's bounding box\n if(d > 0.0) {\n if(d > outerBorder) {\n discard;\n } else {\n outColor = distInterp(vBorderColor, vec4(0), d - outerBorder);\n }\n } else {\n if(d > innerBorder) {\n vec4 outerColor = outerBorder == 0.0 ? vec4(0) : vBorderColor;\n vec4 innerBorderColor = blend(vBorderColor, vColor);\n outColor = distInterp(innerBorderColor, outerColor, d);\n } \n else {\n vec4 outerColor;\n if(innerBorder == 0.0 && outerBorder == 0.0) {\n outerColor = vec4(0);\n } else if(innerBorder == 0.0) {\n outerColor = vBorderColor;\n } else {\n outerColor = blend(vBorderColor, vColor);\n }\n outColor = distInterp(vColor, outerColor, d - innerBorder);\n }\n }\n }\n else {\n outColor = vColor;\n }\n\n ").concat(e.picking?"if(outColor.a == 0.0) discard;\n else outColor = vIndex;":"","\n }\n "),i=function(e,t,n){var r=Vd(e,e.VERTEX_SHADER,t),a=Vd(e,e.FRAGMENT_SHADER,n),i=e.createProgram();if(e.attachShader(i,r),e.attachShader(i,a),e.linkProgram(i),!e.getProgramParameter(i,e.LINK_STATUS))throw new Error("Could not initialize shaders");return i}(t,n,a);i.aPosition=t.getAttribLocation(i,"aPosition"),i.aIndex=t.getAttribLocation(i,"aIndex"),i.aVertType=t.getAttribLocation(i,"aVertType"),i.aTransform=t.getAttribLocation(i,"aTransform"),i.aAtlasId=t.getAttribLocation(i,"aAtlasId"),i.aTex=t.getAttribLocation(i,"aTex"),i.aPointAPointB=t.getAttribLocation(i,"aPointAPointB"),i.aPointCPointD=t.getAttribLocation(i,"aPointCPointD"),i.aLineWidth=t.getAttribLocation(i,"aLineWidth"),i.aColor=t.getAttribLocation(i,"aColor"),i.aCornerRadius=t.getAttribLocation(i,"aCornerRadius"),i.aBorderColor=t.getAttribLocation(i,"aBorderColor"),i.uPanZoomMatrix=t.getUniformLocation(i,"uPanZoomMatrix"),i.uAtlasSize=t.getUniformLocation(i,"uAtlasSize"),i.uBGColor=t.getUniformLocation(i,"uBGColor"),i.uZoom=t.getUniformLocation(i,"uZoom"),i.uTextures=[];for(var o=0;o1&&void 0!==arguments[1]?arguments[1]:sh.SCREEN;this.panZoomMatrix=e,this.renderTarget=t,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(e,t){return!!e.visible()&&(!t||!t.isVisible||t.isVisible(e))}},{key:"drawTexture",value:function(e,t,n){var a=this.atlasManager,o=this.batchManager,s=a.getRenderTypeOpts(n);if(this._isVisible(e,s)){if(this.renderTarget.picking&&s.getTexPickingMode){var l=s.getTexPickingMode(e);if(l===lh)return;if(l==uh)return void this.drawPickingRectangle(e,t,n)}var u,c=r(a.getAtlasInfo(e,n));try{for(c.s();!(u=c.n()).done;){var d=u.value,h=d.atlas,f=d.tex1,p=d.tex2;o.canAddToCurrentBatch(h)||this.endBatch();for(var v=o.getAtlasIndexForBatch(h),g=0,y=[[f,!0],[p,!1]];g=this.maxInstances&&this.endBatch()}}}}catch(e){c.e(e)}finally{c.f()}}}},{key:"setTransformMatrix",value:function(e,t,n,r){var a=!(arguments.length>4&&void 0!==arguments[4])||arguments[4],i=0;if(n.shapeProps&&n.shapeProps.padding&&(i=e.pstyle(n.shapeProps.padding).pfValue),r){var o=r.bb,s=r.tex1,l=r.tex2,u=s.w/(s.w+l.w);a||(u=1-u);var c=this._getAdjustedBB(o,i,a,u);this._applyTransformMatrix(t,c,n,e)}else{var d=n.getBoundingBox(e),h=this._getAdjustedBB(d,i,!0,1);this._applyTransformMatrix(t,h,n,e)}}},{key:"_applyTransformMatrix",value:function(e,t,n,r){var a,i;Jd(e);var o=n.getRotation?n.getRotation(r):0;if(0!==o){var s=n.getRotationPoint(r);eh(e,e,[s.x,s.y]),th(e,e,o);var l=n.getRotationOffset(r);a=l.x+(t.xOffset||0),i=l.y+(t.yOffset||0)}else a=t.x1,i=t.y1;eh(e,e,[a,i]),nh(e,e,[t.w,t.h])}},{key:"_getAdjustedBB",value:function(e,t,n,r){var a=e.x1,i=e.y1,o=e.w,s=e.h;t&&(a-=t,i-=t,o+=2*t,s+=2*t);var l=0,u=o*r;return n&&r<1?o=u:!n&&r<1&&(a+=l=o-u,o=u),{x1:a,y1:i,w:o,h:s,xOffset:l,yOffset:e.yOffset}}},{key:"drawPickingRectangle",value:function(e,t,n){var r=this.atlasManager.getRenderTypeOpts(n),a=this.instanceCount;this.vertTypeBuffer.getView(a)[0]=4,Wd(t,this.indexBuffer.getView(a)),Yd([0,0,0],1,this.colorBuffer.getView(a));var i=this.transformBuffer.getMatrixView(a);this.setTransformMatrix(e,i,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(e,t,n){var r=this.simpleShapeOptions.get(n);if(this._isVisible(e,r)){var a=r.shapeProps,i=this._getVertTypeForShape(e,a.shape);if(void 0===i||r.isSimple&&!r.isSimple(e))this.drawTexture(e,t,n);else{var o=this.instanceCount;if(this.vertTypeBuffer.getView(o)[0]=i,5===i||6===i){var s=r.getBoundingBox(e),l=this._getCornerRadius(e,a.radius,s),u=this.cornerRadiusBuffer.getView(o);u[0]=l,u[1]=l,u[2]=l,u[3]=l,6===i&&(u[0]=0,u[2]=0)}Wd(t,this.indexBuffer.getView(o)),Yd(e.pstyle(a.color).value,e.pstyle(a.opacity).value,this.colorBuffer.getView(o));var c=this.lineWidthBuffer.getView(o);if(c[0]=0,c[1]=0,a.border){var d=e.pstyle("border-width").value;if(d>0){Yd(e.pstyle("border-color").value,e.pstyle("border-opacity").value,this.borderColorBuffer.getView(o));var h=e.pstyle("border-position").value;if("inside"===h)c[0]=0,c[1]=-d;else if("outside"===h)c[0]=d,c[1]=0;else{var f=d/2;c[0]=f,c[1]=-f}}}var p=this.transformBuffer.getMatrixView(o);this.setTransformMatrix(e,p,r),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}},{key:"_getVertTypeForShape",value:function(e,t){switch(e.pstyle(t).value){case"rectangle":return 4;case"ellipse":return 7;case"roundrectangle":case"round-rectangle":return 5;case"bottom-round-rectangle":return 6;default:return}}},{key:"_getCornerRadius",value:function(e,t,n){var r=n.w,a=n.h;if("auto"===e.pstyle(t).value)return Sn(r,a);var i=e.pstyle(t).pfValue,o=r/2,s=a/2;return Math.min(i,s,o)}},{key:"drawEdgeArrow",value:function(e,t,n){if(e.visible()){var r,a,i,o=e._private.rscratch;if("source"===n?(r=o.arrowStartX,a=o.arrowStartY,i=o.srcArrowAngle):(r=o.arrowEndX,a=o.arrowEndY,i=o.tgtArrowAngle),!(isNaN(r)||null==r||isNaN(a)||null==a||isNaN(i)||null==i))if("none"!==e.pstyle(n+"-arrow-shape").value){var s=e.pstyle(n+"-arrow-color").value,l=e.pstyle("opacity").value*e.pstyle("line-opacity").value,u=e.pstyle("width").pfValue,c=e.pstyle("arrow-scale").value,d=this.r.getArrowWidth(u,c),h=this.instanceCount,f=this.transformBuffer.getMatrixView(h);Jd(f),eh(f,f,[r,a]),nh(f,f,[d,d]),th(f,f,i),this.vertTypeBuffer.getView(h)[0]=3,Wd(t,this.indexBuffer.getView(h)),Yd(s,l,this.colorBuffer.getView(h)),this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}},{key:"drawEdgeLine",value:function(e,t){if(e.visible()){var n=this._getEdgePoints(e);if(n){var r=e.pstyle("opacity").value,a=e.pstyle("line-opacity").value,i=e.pstyle("width").pfValue,o=e.pstyle("line-color").value,s=r*a;if(n.length/2+this.instanceCount>this.maxInstances&&this.endBatch(),4==n.length){var l=this.instanceCount;this.vertTypeBuffer.getView(l)[0]=1,Wd(t,this.indexBuffer.getView(l)),Yd(o,s,this.colorBuffer.getView(l)),this.lineWidthBuffer.getView(l)[0]=i;var u=this.pointAPointBBuffer.getView(l);u[0]=n[0],u[1]=n[1],u[2]=n[2],u[3]=n[3],this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}else for(var c=0;c=this.maxInstances&&this.endBatch()}}}}},{key:"_getEdgePoints",value:function(e){var t=e._private.rscratch;if(!t.badLine&&null!=t.allpts&&!isNaN(t.allpts[0])){var n=t.allpts;if(4==n.length)return n;var r=this._getNumSegments(e);return this._getCurveSegmentPoints(n,r)}}},{key:"_getNumSegments",value:function(e){return Math.min(Math.max(15,5),this.maxInstances)}},{key:"_getCurveSegmentPoints",value:function(e,t){if(4==e.length)return e;for(var n=Array(2*(t+1)),r=0;r<=t;r++)if(0==r)n[0]=e[0],n[1]=e[1];else if(r==t)n[2*r]=e[e.length-2],n[2*r+1]=e[e.length-1];else{var a=r/t;this._setCurvePoint(e,a,n,2*r)}return n}},{key:"_setCurvePoint",value:function(e,t,n,r){if(!(e.length<=2)){for(var a=Array(e.length-2),i=0;i0}},u=function(e){return"yes"===e.pstyle("text-events").strValue?uh:lh},c=function(e){var t=e.position(),n=t.x,r=t.y,a=e.outerWidth(),i=e.outerHeight();return{w:a,h:i,x1:n-a/2,y1:r-i/2}};n.drawing.addAtlasCollection("node",{texRows:e.webglTexRowsNodes}),n.drawing.addAtlasCollection("label",{texRows:e.webglTexRows}),n.drawing.addTextureAtlasRenderType("node-body",{collection:"node",getKey:t.getStyleKey,getBoundingBox:t.getElementBox,drawElement:t.drawElement}),n.drawing.addSimpleShapeRenderType("node-body",{getBoundingBox:c,isSimple:Xd,shapeProps:{shape:"shape",color:"background-color",opacity:"background-opacity",radius:"corner-radius",border:!0}}),n.drawing.addSimpleShapeRenderType("node-overlay",{getBoundingBox:c,isVisible:l("overlay"),shapeProps:{shape:"overlay-shape",color:"overlay-color",opacity:"overlay-opacity",padding:"overlay-padding",radius:"overlay-corner-radius"}}),n.drawing.addSimpleShapeRenderType("node-underlay",{getBoundingBox:c,isVisible:l("underlay"),shapeProps:{shape:"underlay-shape",color:"underlay-color",opacity:"underlay-opacity",padding:"underlay-padding",radius:"underlay-corner-radius"}}),n.drawing.addTextureAtlasRenderType("label",{collection:"label",getTexPickingMode:u,getKey:fh(t.getLabelKey,null),getBoundingBox:ph(t.getLabelBox,null),drawClipped:!0,drawElement:t.drawLabel,getRotation:o(null),getRotationPoint:t.getLabelRotationPoint,getRotationOffset:t.getLabelRotationOffset,isVisible:s("label")}),n.drawing.addTextureAtlasRenderType("edge-source-label",{collection:"label",getTexPickingMode:u,getKey:fh(t.getSourceLabelKey,"source"),getBoundingBox:ph(t.getSourceLabelBox,"source"),drawClipped:!0,drawElement:t.drawSourceLabel,getRotation:o("source"),getRotationPoint:t.getSourceLabelRotationPoint,getRotationOffset:t.getSourceLabelRotationOffset,isVisible:s("source-label")}),n.drawing.addTextureAtlasRenderType("edge-target-label",{collection:"label",getTexPickingMode:u,getKey:fh(t.getTargetLabelKey,"target"),getBoundingBox:ph(t.getTargetLabelBox,"target"),drawClipped:!0,drawElement:t.drawTargetLabel,getRotation:o("target"),getRotationPoint:t.getTargetLabelRotationPoint,getRotationOffset:t.getTargetLabelRotationOffset,isVisible:s("target-label")});var d=_e((function(){console.log("garbage collect flag set"),n.data.gc=!0}),1e4);n.onUpdateEleCalcs((function(e,t){var r=!1;t&&t.length>0&&(r|=n.drawing.invalidate(t)),r&&d()})),function(e){var t=e.render;e.render=function(n){n=n||{};var r=e.cy;e.webgl&&(r.zoom()>sd?(!function(e){var t=e.data.contexts[e.WEBGL];t.clear(t.COLOR_BUFFER_BIT|t.DEPTH_BUFFER_BIT)}(e),t.call(e,n)):(!function(e){var t=function(t){t.save(),t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,e.canvasWidth,e.canvasHeight),t.restore()};t(e.data.contexts[e.NODE]),t(e.data.contexts[e.DRAG])}(e),yh(e,n,sh.SCREEN)))};var n=e.matchCanvasSize;e.matchCanvasSize=function(t){n.call(e,t),e.pickingFrameBuffer.setFramebufferAttachmentSizes(e.canvasWidth,e.canvasHeight),e.pickingFrameBuffer.needsDraw=!0},e.findNearestElements=function(t,n,a,o){return function(e,t,n){var a,o,s,l=function(e,t,n){var r,a,o,s,l=jd(e),u=l.pan,c=l.zoom,d=function(e,t,n,r,a){var i=r*n+t.x,o=a*n+t.y;return[i,o=Math.round(e.canvasHeight-o)]}(e,u,c,t,n),h=i(d,2),f=h[0],p=h[1],v=6;if(r=f-v/2,a=p-v/2,s=v,0===(o=v)||0===s)return[];var g=e.data.contexts[e.WEBGL];g.bindFramebuffer(g.FRAMEBUFFER,e.pickingFrameBuffer),e.pickingFrameBuffer.needsDraw&&(g.viewport(0,0,g.canvas.width,g.canvas.height),yh(e,null,sh.PICKING),e.pickingFrameBuffer.needsDraw=!1);var y=o*s,m=new Uint8Array(4*y);g.readPixels(r,a,o,s,g.RGBA,g.UNSIGNED_BYTE,m),g.bindFramebuffer(g.FRAMEBUFFER,null);for(var b=new Set,x=0;x=0&&b.add(w)}return b}(e,t,n),u=e.getCachedZSortedEles(),c=r(l);try{for(c.s();!(s=c.n()).done;){var d=u[s.value];if(!a&&d.isNode()&&(a=d),!o&&d.isEdge()&&(o=d),a&&o)break}}catch(e){c.e(e)}finally{c.f()}return[a,o].filter(Boolean)}(e,t,n)};var a=e.invalidateCachedZSortedEles;e.invalidateCachedZSortedEles=function(){a.call(e),e.pickingFrameBuffer.needsDraw=!0};var o=e.notify;e.notify=function(t,n){o.call(e,t,n),"viewport"===t||"bounds"===t?e.pickingFrameBuffer.needsDraw=!0:"background"===t&&e.drawing.invalidate(n,{type:"node-body"})}}(n)};var fh=function(e,t){return function(n){var r=e(n),a=hh(n,t);return a.length>1?a.map((function(e,t){return"".concat(r,"_").concat(t)})):r}},ph=function(e,t){return function(n,r){var a=e(n);if("string"==typeof r){var i=r.indexOf("_");if(i>0){var o=Number(r.substring(i+1)),s=hh(n,t),l=a.h/s.length,u=l*o,c=a.y1+u;return{x1:a.x1,w:a.w,y1:c,h:l,yOffset:u}}}return a}};function vh(e,t){var n=e.canvasWidth,r=e.canvasHeight,a=jd(e),i=a.pan,o=a.zoom;t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,n,r),t.translate(i.x,i.y),t.scale(o,o)}function gh(e,t,n){var r=e.drawing;t+=1,n.isNode()?(r.drawNode(n,t,"node-underlay"),r.drawNode(n,t,"node-body"),r.drawTexture(n,t,"label"),r.drawNode(n,t,"node-overlay")):(r.drawEdgeLine(n,t),r.drawEdgeArrow(n,t,"source"),r.drawEdgeArrow(n,t,"target"),r.drawTexture(n,t,"label"),r.drawTexture(n,t,"edge-source-label"),r.drawTexture(n,t,"edge-target-label"))}function yh(e,t,n){var a;e.webglDebug&&(a=performance.now());var i=e.drawing,o=0;if(n.screen&&e.data.canvasNeedsRedraw[e.SELECT_BOX]&&function(e,t){e.drawSelectionRectangle(t,(function(t){return vh(e,t)}))}(e,t),e.data.canvasNeedsRedraw[e.NODE]||n.picking){var s=e.data.contexts[e.WEBGL];n.screen?(s.clearColor(0,0,0,0),s.enable(s.BLEND),s.blendFunc(s.ONE,s.ONE_MINUS_SRC_ALPHA)):s.disable(s.BLEND),s.clear(s.COLOR_BUFFER_BIT|s.DEPTH_BUFFER_BIT),s.viewport(0,0,s.canvas.width,s.canvas.height);var l=function(e){var t=e.canvasWidth,n=e.canvasHeight,r=jd(e),a=r.pan,i=r.zoom,o=Qd();eh(o,o,[a.x,a.y]),nh(o,o,[i,i]);var s=Qd();!function(e,t,n){e[0]=2/t,e[1]=0,e[2]=0,e[3]=0,e[4]=-2/n,e[5]=0,e[6]=-1,e[7]=1,e[8]=1}(s,t,n);var l,u,c,d,h,f,p,v,g,y,m,b,x,w,E,k,T,C,P,S,B,D=Qd();return l=D,c=o,d=(u=s)[0],h=u[1],f=u[2],p=u[3],v=u[4],g=u[5],y=u[6],m=u[7],b=u[8],x=c[0],w=c[1],E=c[2],k=c[3],T=c[4],C=c[5],P=c[6],S=c[7],B=c[8],l[0]=x*d+w*p+E*y,l[1]=x*h+w*v+E*m,l[2]=x*f+w*g+E*b,l[3]=k*d+T*p+C*y,l[4]=k*h+T*v+C*m,l[5]=k*f+T*g+C*b,l[6]=P*d+S*p+B*y,l[7]=P*h+S*v+B*m,l[8]=P*f+S*g+B*b,D}(e),u=e.getCachedZSortedEles();if(o=u.length,i.startFrame(l,n),n.screen){for(var c=0;c0&&i>0){h.clearRect(0,0,a,i),h.globalCompositeOperation="source-over";var f=this.getCachedZSortedEles();if(e.full)h.translate(-n.x1*l,-n.y1*l),h.scale(l,l),this.drawElements(h,f),h.scale(1/l,1/l),h.translate(n.x1*l,n.y1*l);else{var p=t.pan(),v={x:p.x*l,y:p.y*l};l*=t.zoom(),h.translate(v.x,v.y),h.scale(l,l),this.drawElements(h,f),h.scale(1/l,1/l),h.translate(-v.x,-v.y)}e.bg&&(h.globalCompositeOperation="destination-over",h.fillStyle=e.bg,h.rect(0,0,a,i),h.fill())}return d},Ch.png=function(e){return Sh(e,this.bufferCanvasImage(e),"image/png")},Ch.jpg=function(e){return Sh(e,this.bufferCanvasImage(e),"image/jpeg")};var Bh={nodeShapeImpl:function(e,t,n,r,a,i,o,s){switch(e){case"ellipse":return this.drawEllipsePath(t,n,r,a,i);case"polygon":return this.drawPolygonPath(t,n,r,a,i,o);case"round-polygon":return this.drawRoundPolygonPath(t,n,r,a,i,o,s);case"roundrectangle":case"round-rectangle":return this.drawRoundRectanglePath(t,n,r,a,i,s);case"cutrectangle":case"cut-rectangle":return this.drawCutRectanglePath(t,n,r,a,i,o,s);case"bottomroundrectangle":case"bottom-round-rectangle":return this.drawBottomRoundRectanglePath(t,n,r,a,i,s);case"barrel":return this.drawBarrelPath(t,n,r,a,i)}}},Dh=Ah,_h=Ah.prototype;function Ah(e){var t=this,n=t.cy.window().document;e.webgl&&(_h.CANVAS_LAYERS=t.CANVAS_LAYERS=4,console.log("webgl rendering enabled")),t.data={canvases:new Array(_h.CANVAS_LAYERS),contexts:new Array(_h.CANVAS_LAYERS),canvasNeedsRedraw:new Array(_h.CANVAS_LAYERS),bufferCanvases:new Array(_h.BUFFER_COUNT),bufferContexts:new Array(_h.CANVAS_LAYERS)};var r="-webkit-tap-highlight-color",a="rgba(0,0,0,0)";t.data.canvasContainer=n.createElement("div");var i=t.data.canvasContainer.style;t.data.canvasContainer.style[r]=a,i.position="relative",i.zIndex="0",i.overflow="hidden";var o=e.cy.container();o.appendChild(t.data.canvasContainer),o.style[r]=a;var s={"-webkit-user-select":"none","-moz-user-select":"-moz-none","user-select":"none","-webkit-tap-highlight-color":"rgba(0,0,0,0)","outline-style":"none"};d&&d.userAgent.match(/msie|trident|edge/i)&&(s["-ms-touch-action"]="none",s["touch-action"]="none");for(var l=0;l<_h.CANVAS_LAYERS;l++){var u=t.data.canvases[l]=n.createElement("canvas"),c=_h.CANVAS_TYPES[l];t.data.contexts[l]=u.getContext(c),t.data.contexts[l]||tt("Could not create canvas of type "+c),Object.keys(s).forEach((function(e){u.style[e]=s[e]})),u.style.position="absolute",u.setAttribute("data-id","layer"+l),u.style.zIndex=String(_h.CANVAS_LAYERS-l),t.data.canvasContainer.appendChild(u),t.data.canvasNeedsRedraw[l]=!1}t.data.topCanvas=t.data.canvases[0],t.data.canvases[_h.NODE].setAttribute("data-id","layer"+_h.NODE+"-node"),t.data.canvases[_h.SELECT_BOX].setAttribute("data-id","layer"+_h.SELECT_BOX+"-selectbox"),t.data.canvases[_h.DRAG].setAttribute("data-id","layer"+_h.DRAG+"-drag"),t.data.canvases[_h.WEBGL]&&t.data.canvases[_h.WEBGL].setAttribute("data-id","layer"+_h.WEBGL+"-webgl");for(l=0;l<_h.BUFFER_COUNT;l++)t.data.bufferCanvases[l]=n.createElement("canvas"),t.data.bufferContexts[l]=t.data.bufferCanvases[l].getContext("2d"),t.data.bufferCanvases[l].style.position="absolute",t.data.bufferCanvases[l].setAttribute("data-id","buffer"+l),t.data.bufferCanvases[l].style.zIndex=String(-l-1),t.data.bufferCanvases[l].style.visibility="hidden";t.pathsEnabled=!0;var h=Qt(),f=function(e){return{x:-e.w/2,y:-e.h/2}},p=function(e){return e[0]._private.nodeKey},v=function(e){return e[0]._private.labelStyleKey},g=function(e){return e[0]._private.sourceLabelStyleKey},y=function(e){return e[0]._private.targetLabelStyleKey},m=function(e,n,r,a,i){return t.drawElement(e,n,r,!1,!1,i)},b=function(e,n,r,a,i){return t.drawElementText(e,n,r,a,"main",i)},x=function(e,n,r,a,i){return t.drawElementText(e,n,r,a,"source",i)},w=function(e,n,r,a,i){return t.drawElementText(e,n,r,a,"target",i)},E=function(e){return e.boundingBox(),e[0]._private.bodyBounds},k=function(e){return e.boundingBox(),e[0]._private.labelBounds.main||h},T=function(e){return e.boundingBox(),e[0]._private.labelBounds.source||h},C=function(e){return e.boundingBox(),e[0]._private.labelBounds.target||h},P=function(e,t){return t},S=function(e){return{x:((t=E(e)).x1+t.x2)/2,y:(t.y1+t.y2)/2};var t},B=function(e,t,n){var r=e?e+"-":"";return{x:t.x+n.pstyle(r+"text-margin-x").pfValue,y:t.y+n.pstyle(r+"text-margin-y").pfValue}},D=function(e,t,n){var r=e[0]._private.rscratch;return{x:r[t],y:r[n]}},_=function(e){return B("",D(e,"labelX","labelY"),e)},A=function(e){return B("source",D(e,"sourceLabelX","sourceLabelY"),e)},M=function(e){return B("target",D(e,"targetLabelX","targetLabelY"),e)},R=function(e){return f(E(e))},I=function(e){return f(T(e))},N=function(e){return f(C(e))},L=function(e){var t=k(e),n=f(k(e));if(e.isNode()){switch(e.pstyle("text-halign").value){case"left":n.x=-t.w-(t.leftPad||0);break;case"right":n.x=-(t.rightPad||0)}switch(e.pstyle("text-valign").value){case"top":n.y=-t.h-(t.topPad||0);break;case"bottom":n.y=-(t.botPad||0)}}return n},z=t.data.eleTxrCache=new cd(t,{getKey:p,doesEleInvalidateKey:function(e){var t=e[0]._private;return!(t.oldBackgroundTimestamp===t.backgroundTimestamp)},drawElement:m,getBoundingBox:E,getRotationPoint:S,getRotationOffset:R,allowEdgeTxrCaching:!1,allowParentTxrCaching:!1}),O=t.data.lblTxrCache=new cd(t,{getKey:v,drawElement:b,getBoundingBox:k,getRotationPoint:_,getRotationOffset:L,isVisible:P}),V=t.data.slbTxrCache=new cd(t,{getKey:g,drawElement:x,getBoundingBox:T,getRotationPoint:A,getRotationOffset:I,isVisible:P}),F=t.data.tlbTxrCache=new cd(t,{getKey:y,drawElement:w,getBoundingBox:C,getRotationPoint:M,getRotationOffset:N,isVisible:P}),j=t.data.lyrTxrCache=new hd(t);t.onUpdateEleCalcs((function(e,t){z.invalidateElements(t),O.invalidateElements(t),V.invalidateElements(t),F.invalidateElements(t),j.invalidateElements(t);for(var n=0;n { + cy.resize(); + cy.fit(cy.nodes().boundingBox(), GRAPH_PADDING); + cy.center(); + }); + + if (!isEnoughAreaWithoutBorders(cy, GRAPH_PADDING)) { + cy.destroy(); + showResizeWarning(); + } else { + // When clicked, we display the details for the node in the bottom tree view + cy.on("tap", "node", function (evt) { + const id = evt.target.id(); + vscode.postMessage({ + command: "selected", + nodeId: id, + }); + }); + + // === Tooltip Hover Handler === + cy.nodes().on("mouseover", (event) => { + const node = event.target; + + const hoverDiv = document.createElement("pre"); + const id = node.id(); + const tooltip = tooltips[id]; + hoverDiv.innerText = tooltip; + hoverDiv.className = "hover-box"; + document.body.appendChild(hoverDiv); + + function updatePosition() { + const { left, top } = getTooltipPosition( + node, + cy.container(), + hoverDiv + ); + hoverDiv.style.left = `${left}px`; + hoverDiv.style.top = `${top}px`; + } + + updatePosition(); + cy.on("pan zoom resize", updatePosition); + node.on("position", updatePosition); + + node.once("mouseout", () => { + hoverDiv.remove(); + cy.off("pan zoom resize", updatePosition); + node.off("position", updatePosition); + }); + }); + + function redrawBorders() { + deleteAllBorders(); + drawBorderAndIconForEachExplainNode(cy, GRAPH_PADDING); + } + + cy.on("pan zoom resize", redrawBorders); + drawBorderAndIconForEachExplainNode(cy, GRAPH_PADDING); + } +} diff --git a/media/explain/graphUtils.js b/media/explain/graphUtils.js new file mode 100644 index 00000000..98fc8585 --- /dev/null +++ b/media/explain/graphUtils.js @@ -0,0 +1,113 @@ +export const MIN_DISTANCE_TO_VIEWPORT = 4; +export const TOOLTIP_OFFSET = 20; + +// === Node Position Utilities === + +export function getNodeTopLeftAbsolute(node, cy) { + const containerRect = cy.container().getBoundingClientRect(); + const pos = node.position(); + const zoom = cy.zoom(); + const pan = cy.pan(); + + const renderedX = pos.x * zoom + pan.x; + const renderedY = pos.y * zoom + pan.y; + + return { + x: containerRect.left + renderedX - node.renderedWidth() / 2, + y: containerRect.top + renderedY - node.renderedHeight() / 2, + }; +} + +// === Border Geometry Utilities === + +export function getTopLeftForBorder(x, y, padX, padY, iconH, iconGap) { + return { + x: x - padX - 2, // slight adjustment + y: y - padY - iconH - iconGap, + }; +} + +export function getBorderWidthAndHeight( + padX, + nodeW, + padY, + nodeH, + iconH, + iconGap +) { + return { + width: padX * 2 + nodeW, + height: padY * 2 + iconH + iconGap + nodeH, + }; +} + +// === Tooltip Position Utility === +export function getTooltipPosition(node, container, tooltipBox) { + const { x, y } = node.renderedPosition(); + const containerRect = container.getBoundingClientRect(); + const boxRect = tooltipBox.getBoundingClientRect(); + + let left = x + containerRect.left - boxRect.width / 2; + let top = + y - + node.renderedOuterHeight() / 2 + + containerRect.top - + boxRect.height - + TOOLTIP_OFFSET; + + // Prevent overflow + if (left < MIN_DISTANCE_TO_VIEWPORT) left = MIN_DISTANCE_TO_VIEWPORT; + if (left + boxRect.width > window.innerWidth - MIN_DISTANCE_TO_VIEWPORT) { + left = window.innerWidth - boxRect.width - MIN_DISTANCE_TO_VIEWPORT; + } + + if (top < MIN_DISTANCE_TO_VIEWPORT) { + top = y + containerRect.top + node.renderedOuterHeight() / 2; + } + + return { left, top }; +} + +export function showResizeWarning() { + const warningDiv = document.createElement("div"); + warningDiv.className = "warning-div" + + const h1 = document.createElement("h1"); + h1.className = "warning-div-title" + h1.textContent = "Window is too small. Make your window larger and run again."; + + warningDiv.appendChild(h1); + document.body.appendChild(warningDiv); +} + +export function isEnoughAreaWithoutBorders(cy, windowPadding) { + const windowWidth = window.innerWidth; + const windowHeight = window.innerHeight; + + let areaNeededForAllNodes = 0; + let maxHeightNeededForNode = 60; + let maxWidthNeededForNode = 100; + + cy.nodes().forEach(node => { + const nodeW = node.renderedWidth(); + const nodeH = node.renderedHeight(); + areaNeededForAllNodes += nodeW * nodeH + maxHeightNeededForNode = Math.max(maxHeightNeededForNode, nodeH); + maxWidthNeededForNode = Math.max(maxWidthNeededForNode, nodeW); + }); + + const usableWidth = windowWidth - 2 * windowPadding; + const usableHeight = windowHeight - 2 * windowPadding; + + const maxCols = Math.floor(usableWidth / maxWidthNeededForNode); + const maxRows = Math.floor(usableHeight / maxHeightNeededForNode); + + const maxNodesThatCanFit = maxCols * maxRows; + + return cy.nodes().length <= maxNodesThatCanFit; +} + +export function isWindowTooSmall(windowPadding){ + const extraRoom = 50 + return windowPadding * 2 >= window.innerWidth || windowPadding * 2 + extraRoom >= window.innerHeight +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4f252276..aee556d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@octokit/rest": "^21.1.1", "chart.js": "^4.4.2", "csv": "^6.1.3", + "cytoscape": "^3.32.1", "json-to-markdown-table": "^1.0.0", "lru-cache": "^6.0.0", "node-fetch": "^3.3.1", @@ -5580,6 +5581,15 @@ "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.5.2.tgz", "integrity": "sha512-RFPahj0sXcmUyjrObAK+DOWtMvMIFV328n4qZJhgX3x2RqkQgOTU2mCUmiFR0CzM6AzChlRSUErjiJeEt8BaQA==" }, + "node_modules/cytoscape": { + "version": "3.32.1", + "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.1.tgz", + "integrity": "sha512-dbeqFTLYEwlFg7UGtcZhCCG/2WayX72zK3Sq323CEX29CY81tYfVhw1MIdduCtpstB0cTOhJswWlM/OEB3Xp+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, "node_modules/dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", diff --git a/package.json b/package.json index 02ca40d9..f3fc06b7 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "scripts": { "test": "vitest", "dsc": "npx tsx src/dsc", + "prepackage": "rm -rf media/explain/cytoscape.min.js && cp node_modules/cytoscape/dist/cytoscape.min.js media/explain", "package": "vsce package", "vscode:prepublish": "rm -rf dist && npm run webpack && npm run dsc", "webpack": "vscd --clean && webpack --mode development", @@ -567,6 +568,12 @@ "category": "Db2 for i", "icon": "$(gear)" }, + { + "command": "vscode-db2i.dove.export", + "title": "Export current VE data", + "category": "Db2 for i", + "icon": "$(file)" + }, { "command": "vscode-db2i.dove.node.copy", "title": "Copy value", @@ -864,6 +871,10 @@ "command": "vscode-db2i.dove.editSettings", "when": "vscode-db2i:explaining == true" }, + { + "command": "vscode-db2i.dove.export", + "when": "vscode-db2i:explaining == true" + }, { "command": "vscode-db2i.dove.node.copy", "when": "never" @@ -968,6 +979,11 @@ "group": "navigation@1", "when": "view == vscode-db2i.dove.nodes" }, + { + "command": "vscode-db2i.dove.export", + "group": "navigation@2", + "when": "view == vscode-db2i.dove.nodes" + }, { "command": "vscode-db2i.dove.close", "group": "navigation@3", @@ -1526,6 +1542,7 @@ "@octokit/rest": "^21.1.1", "chart.js": "^4.4.2", "csv": "^6.1.3", + "cytoscape": "^3.32.1", "json-to-markdown-table": "^1.0.0", "lru-cache": "^6.0.0", "node-fetch": "^3.3.1", diff --git a/src/contextProvider.ts b/src/contextProvider.ts new file mode 100644 index 00000000..9424ca6b --- /dev/null +++ b/src/contextProvider.ts @@ -0,0 +1,16 @@ +import type { ExtensionContext } from "vscode"; + +export class ContextProvider { + private static ctx: ExtensionContext | undefined; + + public static setContext(context: ExtensionContext) { + ContextProvider.ctx = context; + } + + public static getContext(): ExtensionContext { + if (!ContextProvider.ctx) { + throw new Error("Context is not set yet"); + } + return ContextProvider.ctx; + } +} diff --git a/src/extension.ts b/src/extension.ts index 219b0a39..520e4194 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -26,6 +26,7 @@ import { queryHistory } from "./views/queryHistoryView"; import { registerCopilotProvider } from "./aiProviders/copilot"; import { registerDb2iTablesProvider } from "./aiProviders/continue/listTablesContextProvider"; import { setCheckerAvailableContext } from "./language/providers/problemProvider"; +import { ContextProvider } from "./contextProvider"; export interface Db2i { sqlJobManager: SQLJobManager, @@ -42,6 +43,7 @@ export function activate(context: vscode.ExtensionContext): Db2i { console.log(`Congratulations, your extension "vscode-db2i" is now active!`); loadBase(context); + ContextProvider.setContext(context); const exampleBrowser = new ExampleBrowser(context); const selfCodesView = new selfCodesResultsView(context); diff --git a/src/views/cytoscape/index.ts b/src/views/cytoscape/index.ts index 3f670ecb..20ac0f40 100644 --- a/src/views/cytoscape/index.ts +++ b/src/views/cytoscape/index.ts @@ -1,47 +1,60 @@ import { ViewColumn, window } from "vscode"; +import * as vscode from "vscode"; +import { ContextProvider } from "../../contextProvider"; +import { icons } from "../results/explain/icons"; +import { ExplainNode } from "../results/explain/nodes"; -type Styles = {[key: string]: string}; +export type Styles = { [key: string]: string }; export interface Element { - data: {id: string, label: string}, - style: Styles + data: { id: string; label: string }; + style: Styles; + classes: string; + grabbable: boolean; } export interface Edge { - data: {id: string, source: string, target: string} + data: { id: string; source: string; target: string }; } -interface NewNode { - label: string, - styles?: Styles, - parent?: string, - data?: any; +interface NewNode { + label: string; + styles?: Styles; + parent?: string; + data?: ExplainNode; } const randomId = () => Math.random().toString(36).substring(7); export class CytoscapeGraph { private elementData = new Map(); + private tooltips = {}; private elements: Element[] = []; private edges: Edge[] = []; constructor() {} addNode(node: NewNode): string { - const id = randomId(); // TODO: is this unique enough? + const id = randomId(); if (node.data) { this.elementData.set(id, node.data); + const tooltip = node.data.tooltipProps + .map((prop) => `${prop.title}: ${prop.value}`) + .join("\n"); + this.tooltips[id] = tooltip; } this.elements.push({ - data: {id, label: node.label}, - style: node.styles || {} + data: { id, label: node.label }, + style: node.styles || {}, + classes: "l1", + grabbable: false }); if (node.parent) { this.edges.push({ - data: {id: randomId(), source: node.parent, target: id} + data: { id: randomId(), source:id , target: node.parent }, }); } @@ -49,112 +62,79 @@ export class CytoscapeGraph { } createView(title: string, onNodeSelected: (data: unknown) => void): any { - const webview = window.createWebviewPanel(`c`, title, {viewColumn: ViewColumn.One}, {enableScripts: true, retainContextWhenHidden: true}); - webview.webview.html = this.getHtml(); - - webview.webview.onDidReceiveMessage((message) => { - if (message.command === 'selected') { - const data = this.elementData.get(message.nodeId); - onNodeSelected(data); - } - }, undefined, []); + const webview = window.createWebviewPanel( + `c`, + title, + { viewColumn: ViewColumn.One }, + { enableScripts: true, retainContextWhenHidden: true } + ); + webview.webview.html = this.getHtml(webview.webview); + + webview.webview.onDidReceiveMessage( + (message) => { + if (message.command === "selected") { + const data = this.elementData.get(message.nodeId); + onNodeSelected(data); + } + }, + undefined, + [] + ); return webview; } - private getHtml(): string { - return /*html*/` + private getUri(path: string[], webview: vscode.Webview): vscode.Uri { + const context = ContextProvider.getContext(); + const vscodeUri = vscode.Uri.joinPath(context.extensionUri, ...path); + return webview.asWebviewUri(vscodeUri); + } + + private getHtml(webview: vscode.Webview): string { + const data = JSON.stringify([...this.elements, ...this.edges]); + const iconMap = JSON.stringify(icons); + const tooltips = JSON.stringify(this.tooltips); + const cssUri = this.getUri( + ["media", "explain", "explain.css"], + webview + ); + + const codiconsUri = this.getUri( + ["media", "explain", "dist", "codicon.css"], + webview + ); + + const cytoscapeUri = this.getUri( + ["media", "explain", "cytoscape.min.js"], + webview + ); + + const explainUri = this.getUri( + ["media", "explain", "explain.js"], + webview + ); + + return /*html*/ ` - - + + + + + -
- - - `; } -} \ No newline at end of file +} diff --git a/src/views/results/explain/contributes.json b/src/views/results/explain/contributes.json index 2d73944d..69383210 100644 --- a/src/views/results/explain/contributes.json +++ b/src/views/results/explain/contributes.json @@ -106,6 +106,12 @@ "category": "Db2 for i", "icon": "$(gear)" }, + { + "command": "vscode-db2i.dove.export", + "title": "Export current VE data", + "category": "Db2 for i", + "icon": "$(file)" + }, { "command": "vscode-db2i.dove.node.copy", "title": "Copy value", @@ -127,6 +133,10 @@ "command": "vscode-db2i.dove.editSettings", "when": "vscode-db2i:explaining == true" }, + { + "command": "vscode-db2i.dove.export", + "when": "vscode-db2i:explaining == true" + }, { "command": "vscode-db2i.dove.node.copy", "when": "never" @@ -143,6 +153,11 @@ "group": "navigation@1", "when": "view == vscode-db2i.dove.nodes" }, + { + "command": "vscode-db2i.dove.export", + "group": "navigation@2", + "when": "view == vscode-db2i.dove.nodes" + }, { "command": "vscode-db2i.dove.close", "group": "navigation@3", diff --git a/src/views/results/explain/doveResultsView.ts b/src/views/results/explain/doveResultsView.ts new file mode 100644 index 00000000..fc9285a3 --- /dev/null +++ b/src/views/results/explain/doveResultsView.ts @@ -0,0 +1,143 @@ +import * as vscode from "vscode"; +import { CancellationToken, Event, EventEmitter, ProviderResult, TreeView, TreeDataProvider, TreeItem, TreeItemCollapsibleState, commands, ThemeIcon } from "vscode"; +import { ExplainNode } from "./nodes"; +import { toDoveTreeDecorationProviderUri } from "./doveTreeDecorationProvider"; + +/** + * Icon labels as defined by the API, along with the name of the icon to display. + * Not surprisingly, the reference link does not provide a complete list of icons. + * TODO: Add missing icons + * @see https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qqqvexpl.html#icon_labels + * @see https://code.visualstudio.com/api/references/icons-in-labels + */ +const icons = { + "Bitmap Merge": `merge`, + "Cache": ``, + "Cache Probe": ``, + "Delete": `trash`, + "Distinct": `list-flat`, + "Dynamic Bitmap": `symbol-misc`, + "Encoded Vector Index": `symbol-reference`, + "Encoded Vector Index, Parallel": `symbol-reference`, + "Final Select": `selection`, + "Hash Grouping": `group-by-ref-type`, + "Hash Join": `add`, + "Hash Scan": `search`, + "Index Grouping": `group-by-ref-type`, + "Index Scan - Key Positioning": `key`, + "Index Scan - Key Positioning, Parallel": `key`, + "Index Scan - Key Selection": `key`, + "Index Scan - Key Selection, Parallel": `key`, + "Insert": `insert`, + "Nested Loop Join": `add`, + "Select": `selection`, + "Skip Sequential Table Scan": `list-unordered`, + "Skip Sequential Table Scan, Parallel": `list-unordered`, + "Sort": `sort-precedence`, + "Sorted List Scan": `list-ordered`, + "Subquery Merge": `merge`, + "Table Probe": `list-selection`, + "Table Scan": `search`, + "Table Scan, Parallel": `search`, + "Temporary Distinct Hash Table": `new-file`, + "Temporary Hash Table": `new-file`, + "Temporary Index": `new-file`, + "Temporary Sorted List": `list-ordered`, + "Temporary Table": `new-file`, + "Union Merge": `merge`, + "User Defined Table Function": `symbol-function`, + "Unknown": `question`, + "Update": `replace`, + "VALUES LIST": `list-flat`, +} + +type ChangeTreeDataEventType = ExplainTreeItem | undefined | null | void; + +export class DoveResultsView implements TreeDataProvider { + private _onDidChangeTreeData: EventEmitter = new EventEmitter(); + readonly onDidChangeTreeData: Event = this._onDidChangeTreeData.event; + + private topNode: ExplainTreeItem; + + private treeView: TreeView; + + constructor() { + this.treeView = vscode.window.createTreeView(`vscode-db2i.dove.nodes`, { treeDataProvider: this, showCollapseAll: true }); + } + + public getTreeView(): TreeView { + return this.treeView; + } + + setRootNode(topNode: ExplainNode): ExplainTreeItem { + this.topNode = new ExplainTreeItem(topNode); + this._onDidChangeTreeData.fire(); + + // Show tree in the view + commands.executeCommand(`setContext`, `vscode-db2i:explaining`, true); + // Ensure that the tree is positioned such that the first element is visible + this.treeView.reveal(this.topNode, { select: false }); + return this.topNode; + } + getRootNode(): ExplainTreeItem { + return this.topNode; + } + + getRootExplainNode(): ExplainNode { + return this.topNode.explainNode; + } + + close(): void { + commands.executeCommand(`setContext`, `vscode-db2i:explaining`, false); + } + + getTreeItem(element: ExplainTreeItem): ExplainTreeItem | Thenable { + return element; + } + + getChildren(element?: ExplainTreeItem): ProviderResult { + if (element) { + return element.getChildren(); + } else if (this.topNode) { + return [this.topNode]; + } else { + return []; + } + } + + getParent?(element: any) { + throw new Error("Method not implemented."); + } + + resolveTreeItem?(item: TreeItem, element: any, token: CancellationToken): ProviderResult { + throw new Error("Method not implemented."); + } +} + +export class ExplainTreeItem extends TreeItem { + explainNode: ExplainNode; + private children: ExplainTreeItem[]; + + constructor(node: ExplainNode) { + super(node.title, node.childrenNodes > 0 ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.None); + this.explainNode = node; + this.contextValue = `explainTreeItem`; + + // If the node is associated with a DB object, display the qualified object name in the description + if (node.objectSchema && node.objectName) { + this.description = node.objectSchema + `.` + node.objectName; + } + + // TODO: ideally the tooltip would be built using a MarkdownString, but regardless of everything tried, 'Loading...' is always displayed + this.tooltip = [node.title, node.tooltipProps.map(prop => prop.title + `: ` + prop.value).join(`\n`), ``].join(`\n`); + this.resourceUri = toDoveTreeDecorationProviderUri(node.highlights); + this.iconPath = new ThemeIcon(icons[node.title] || `server-process`, node.highlights.getPriorityColor()); // `circle-outline` + } + + getChildren(): ExplainTreeItem[] { + if (!this.children) { + this.children = this.explainNode.children.map(c => new ExplainTreeItem(c)); + } + return this.children; + } +} \ No newline at end of file diff --git a/src/views/results/explain/doveTreeDecorationProvider.ts b/src/views/results/explain/doveTreeDecorationProvider.ts index f7977a3f..20893e41 100644 --- a/src/views/results/explain/doveTreeDecorationProvider.ts +++ b/src/views/results/explain/doveTreeDecorationProvider.ts @@ -35,7 +35,7 @@ export class DoveTreeDecorationProvider implements FileDecorationProvider { * @inheritdoc * Provides tree node decorations specific to Db2 for i Visual Explain. */ - async provideFileDecoration(uri: Uri): Promise { + provideFileDecoration(uri: Uri): FileDecoration | null { // Only decorate tree items tagged with the VE scheme if (uri?.scheme === doveUriScheme) { // The Uri path should simply be a number that represents the highlight attributes diff --git a/src/views/results/explain/icons.ts b/src/views/results/explain/icons.ts index 65cb4115..ae29ad4d 100644 --- a/src/views/results/explain/icons.ts +++ b/src/views/results/explain/icons.ts @@ -6,43 +6,116 @@ * @see https://www.ibm.com/docs/en/i/7.5?topic=ssw_ibm_i_75/apis/qqqvexpl.html#icon_labels * @see https://code.visualstudio.com/api/references/icons-in-labels */ -const icons = { - "Bitmap Merge": `merge`, - "Cache": ``, - "Cache Probe": ``, - "Delete": `trash`, - "Distinct": `list-flat`, - "Dynamic Bitmap": `symbol-misc`, - "Encoded Vector Index": `symbol-reference`, - "Encoded Vector Index, Parallel": `symbol-reference`, - "Final Select": `selection`, - "Hash Grouping": `group-by-ref-type`, - "Hash Join": `add`, - "Hash Scan": `search`, - "Index Grouping": `group-by-ref-type`, - "Index Scan - Key Positioning": `key`, - "Index Scan - Key Positioning, Parallel": `key`, - "Index Scan - Key Selection": `key`, - "Index Scan - Key Selection, Parallel": `key`, - "Insert": `insert`, - "Nested Loop Join": `add`, - "Select": `selection`, - "Skip Sequential Table Scan": `list-unordered`, - "Skip Sequential Table Scan, Parallel": `list-unordered`, - "Sort": `sort-precedence`, - "Sorted List Scan": `list-ordered`, - "Subquery Merge": `merge`, - "Table Probe": `list-selection`, - "Table Scan": `search`, - "Table Scan, Parallel": `search`, - "Temporary Distinct Hash Table": `new-file`, - "Temporary Hash Table": `new-file`, - "Temporary Index": `new-file`, - "Temporary Sorted List": `list-ordered`, - "Temporary Table": `new-file`, - "Union Merge": `merge`, - "User Defined Table Function": `symbol-function`, - "Unknown": `question`, - "Update": `replace`, - "VALUES LIST": `list-flat`, -} \ No newline at end of file +export const icons = { + "Add": "add", + "Aggregate": "symbol-constant", + "Aggregate Expression List": "list-unordered", + "Aggregation": "symbol-constant", + "And": "symbol-boolean", + "Assign": "symbol-parameter", + "At Least One": "symbol-enum-member", + "At Most One": "symbol-enum-member", + "Bitmap": "symbol-array", + "Bitmap Merge": "merge", + "Bitmap Probe": "search", + "Bitmap Scan": "search", + "Buffer Scan": "search", + "Building Key": "key", + "Cache": "symbol-event", + "Cache Probe": "search", + "Column": "symbol-field", + "Complicated": "warning", + "Data": "database", + "Delete": "trash", + "Dequeue": "debug-breakpoint-log", + "Derivation Logic": "symbol-operator", + "Distinct": "list-flat", + "Distinct Hash Table Probe": "search", + "Distinct Hash Table Scan": "search", + "Distinct Key Range": "key", + "Divide": "symbol-operator", + "EVI Symbol Probe": "search", + "EVI Symbol Scan": "search", + "Encoded Vector Index": "symbol-reference", + "Enqueue": "debug-breakpoint-log", + "EqualTo": "symbol-boolean", + "Expression Object": "symbol-misc", + "Fetch N Rows": "list-selection", + "Final Select": "selection", + "Function": "symbol-function", + "GreaterThan": "symbol-boolean", + "GreaterThanOrEqualTo": "symbol-boolean", + "Group By Expression List": "group-by-ref-type", + "Hash Grouping": "group-by-ref-type", + "Hash Join": "add", + "Hash Probe": "search", + "Hash Scan": "search", + "Host Variable": "symbol-variable", + "If None One": "symbol-boolean", + "Index Distinct Probe": "search", + "Index Distinct Scan": "search", + "Index Grouping": "group-by-ref-type", + "Index Object": "symbol-object", + "Index Random Input/Output": "symbol-property", + "Insert": "add", + "Key": "key", + "Left Exception Join Fanout": "combine", + "Left Join Fanout": "combine", + "LessThan": "symbol-boolean", + "LessThanOrEqualTo": "symbol-boolean", + "List Scan": "list-unordered", + "Literal": "symbol-number", + "Lock Row For Update": "lock", + "Logic": "symbol-operator", + "Merge": "merge", + "Multiply": "symbol-operator", + "Nested Loop Join": "combine", + "NotEqualTo": "symbol-boolean", + "Object": "symbol-object", + "Or": "symbol-boolean", + "Order By Expression List": "list-ordered", + "Predicate Expression List": "symbol-boolean", + "Predicate Logic": "symbol-boolean", + "Queue": "debug-breakpoint-log", + "Radix Index Probe": "search", + "Radix Index Scan": "search", + "Random Input/Output": "debug-rerun", + "RI Reduction Union": "merge", + "RI Reduction Union 2": "merge", + "Rank": "symbol-number", + "Relation Object": "symbol-object", + "Row Number List Probe": "search", + "Row Number List Scan": "search", + "Scalar Subselect": "symbol-constant", + "Scan": "search", + "Select": "selection", + "Selection Expression List": "list-unordered", + "Single Fanout": "debug-step-into", + "Sort": "sort-precedence", + "Sorted List Probe": "search", + "Sorted List Scan": "list-ordered", + "Special Logic": "symbol-operator", + "Special Register": "symbol-key", + "Subquery Merge": "merge", + "Subtract": "dash", + "Sync Flag": "sync", + "Table Object": "table", + "Table Probe": "list-selection", + "Table Scan": "search", + "TEMPORARY DISTINCT SORTED LIST": "list-flat", + "TEMPORARY INDEX": "file", + "Temporary Buffer": "file-binary", + "Temporary Distinct Hash Table": "new-file", + "Temporary Hash Table": "new-file", + "Temporary Indexed List Scan": "list-unordered", + "Temporary List": "list-unordered", + "Temporary Row Number List": "list-unordered", + "Temporary Sorted List": "list-ordered", + "Union Merge": "merge", + "Union Switch": "merge", + "Unknown": "question", + "Unnest": "symbol-array", + "Update": "replace", + "User Defined Table Function": "symbol-function", + "VALUES LIST": "list-flat" +} diff --git a/src/views/results/explain/nodes.ts b/src/views/results/explain/nodes.ts index a5916d09..8eeee5eb 100644 --- a/src/views/results/explain/nodes.ts +++ b/src/views/results/explain/nodes.ts @@ -2,6 +2,7 @@ import Statement from "../../../database/statement"; import { ThemeColor } from "vscode"; import Configuration from "../../../configuration"; import { DoveNodeView } from "./doveNodeView"; +import { Styles } from "../../cytoscape"; export interface ExplainNode { id: number; @@ -17,6 +18,7 @@ export interface ExplainNode { contextObjects: ContextObject[]; /** Context to set when displaying this node, used to identify additional actions */ nodeContext: string; + styles: Styles } export interface ExplainProperty { @@ -54,10 +56,15 @@ export class ExplainTree { public get(): ExplainNode { return this.topNode; } + + private setNodeShape(node: ExplainNode, shape:string){ + node.styles["shape"] = shape + } private processNode(index: number): ExplainNode { - let node = this.newNode(this.order[index]); let state = new NodeProcessingState(); + let node = this.newNode(this.order[index]); + this.setNodeShape(node, "roundrectangle"); for (const data of this.flatNodes[node.id]) { // When a DELTA_ATTRIBUTES_INDICATOR row is encountered, the rows following it provide new values for previously processed attributes, @@ -128,14 +135,17 @@ export class ExplainTree { return node; } + + private isValidTitle(title:string):boolean{ + return /[a-zA-z]/.test(title) + } /** * Update the node properties */ private updateNode(node: ExplainNode, value: any, state: NodeProcessingState, data: any): void { const title = data.IFA_COLHDG; - // Ignore rows with no title - if (!title) { + if (!this.isValidTitle(title)) { return; } const type = data.IFA_COLTYP; @@ -198,7 +208,8 @@ export class ExplainTree { tooltipProps: [], highlights: new NodeHighlights(), contextObjects: [], - nodeContext: `` + nodeContext: ``, + styles: {} }; } diff --git a/src/views/results/index.ts b/src/views/results/index.ts index 03594316..5bca4f8c 100644 --- a/src/views/results/index.ts +++ b/src/views/results/index.ts @@ -9,9 +9,10 @@ import Document from "../../language/sql/document"; import { ObjectRef, ParsedEmbeddedStatement, StatementGroup, StatementType } from "../../language/sql/types"; import Statement from "../../language/sql/statement"; import { ExplainNode, ExplainTree } from "./explain/nodes"; +import { DoveResultsView, ExplainTreeItem } from "./explain/doveResultsView"; import { DoveNodeView, PropertyNode } from "./explain/doveNodeView"; -import { DoveTreeDecorationProvider } from "./explain/doveTreeDecorationProvider"; import { ResultSetPanelProvider, SqlParameter } from "./resultSetPanelProvider"; +import { DoveTreeDecorationProvider } from "./explain/doveTreeDecorationProvider"; import { generateSqlForAdvisedIndexes } from "./explain/advice"; import { updateStatusBar } from "../jobManager/statusBar"; import { DbCache } from "../../language/providers/logic/cache"; @@ -53,6 +54,8 @@ export function setCancelButtonVisibility(visible: boolean) { let resultSetProvider = new ResultSetPanelProvider(); let explainTree: ExplainTree; +let doveResultsView = new DoveResultsView(); +let doveResultsTreeView: TreeView = doveResultsView.getTreeView(); let doveNodeView = new DoveNodeView(); let doveNodeTreeView: TreeView = doveNodeView.getTreeView(); let doveTreeDecorationProvider = new DoveTreeDecorationProvider(); // Self-registers as a tree decoration providor @@ -61,6 +64,7 @@ export function initialise(context: vscode.ExtensionContext) { setCancelButtonVisibility(false); context.subscriptions.push( + doveResultsTreeView, doveNodeTreeView, vscode.window.registerWebviewViewProvider(`vscode-db2i.resultset`, resultSetProvider, { @@ -99,6 +103,17 @@ export function initialise(context: vscode.ExtensionContext) { } }), + vscode.commands.registerCommand(`vscode-db2i.dove.close`, () => { + doveResultsView.close(); + doveNodeView.close(); + }), + + vscode.commands.registerCommand(`vscode-db2i.dove.displayDetails`, (explainTreeItem: ExplainTreeItem) => { + // When the user clicks for details of a node in the tree, set the focus to that node as a visual indicator tying it to the details tree + doveResultsTreeView.reveal(explainTreeItem, { select: false, focus: true, expand: true }); + doveNodeView.setNode(explainTreeItem.explainNode); + }), + vscode.commands.registerCommand(`vscode-db2i.dove.node.copy`, (propertyNode: PropertyNode) => { if (propertyNode.description && typeof propertyNode.description === `string`) { vscode.env.clipboard.writeText(propertyNode.description); @@ -114,6 +129,15 @@ export function initialise(context: vscode.ExtensionContext) { vscode.commands.executeCommand('workbench.action.openSettings', 'vscode-db2i.visualExplain'); }), + vscode.commands.registerCommand(`vscode-db2i.dove.export`, () => { + vscode.workspace.openTextDocument({ + language: `json`, + content: JSON.stringify(doveResultsView.getRootExplainNode(), null, 2) + }).then(doc => { + vscode.window.showTextDocument(doc); + }); + }), + vscode.commands.registerCommand(`vscode-db2i.dove.generateSqlForAdvisedIndexes`, () => { const scriptContent = generateSqlForAdvisedIndexes(explainTree); @@ -238,6 +262,8 @@ async function runHandler(options?: StatementInfo) { const optionsIsValid = (options?.content !== undefined); let editor = vscode.window.activeTextEditor; + vscode.commands.executeCommand('vscode-db2i.dove.close'); + if (optionsIsValid || (editor && editor.document.languageId === `sql`)) { let chosenView = resultSetProvider; @@ -384,6 +410,9 @@ async function runHandler(options?: StatementInfo) { explainTree = new ExplainTree(explained.vedata); const topLevel = explainTree.get(); + const rootNode = doveResultsView.setRootNode(topLevel); + doveNodeView.setNode(rootNode.explainNode); + doveTreeDecorationProvider.updateTreeItems(rootNode); const graph = new CytoscapeGraph(); @@ -392,6 +421,7 @@ async function runHandler(options?: StatementInfo) { label: node.title, parent: parent, data: node, + styles: node.styles }); if (node.children) { @@ -400,7 +430,7 @@ async function runHandler(options?: StatementInfo) { } } } - + addNode(topLevel); const webview = graph.createView(`Explain Graph`, (data: ExplainNode) => { From 193d4d0b4d0993f21501c8977fe0224fcd1e2773 Mon Sep 17 00:00:00 2001 From: Jonathan Zak Date: Wed, 23 Jul 2025 10:42:15 -0400 Subject: [PATCH 5/5] Fix active colour on nodes --- media/explain/explain.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/media/explain/explain.js b/media/explain/explain.js index 256c9d6b..3714a478 100644 --- a/media/explain/explain.js +++ b/media/explain/explain.js @@ -27,19 +27,25 @@ if (isWindowTooSmall(GRAPH_PADDING)) { selector: "node", style: { padding: "5px", - width: "150px", + width: "150px", shape: "roundrectangle", "background-color": "lightgray", - color: "var(--vscode-list-activeSelectionForeground)", + color: "black", label: "data(label)", - "text-wrap": "wrap", - "text-max-width": "150px", + "text-wrap": "wrap", + "text-max-width": "150px", "text-valign": "center", "text-halign": "center", "font-size": "14px", "line-height": "1.2", }, }, + { + selector: "node:selected", + style: { + "background-color": "deepskyblue", + }, + }, { selector: "edge", style: { @@ -65,8 +71,8 @@ if (isWindowTooSmall(GRAPH_PADDING)) { }); window.addEventListener("resize", () => { - cy.resize(); - cy.fit(cy.nodes().boundingBox(), GRAPH_PADDING); + cy.resize(); + cy.fit(cy.nodes().boundingBox(), GRAPH_PADDING); cy.center(); });