UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

1,116 lines 41.4 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Model = void 0; var util_1 = require("../util"); var common_1 = require("../common"); var geometry_1 = require("../geometry"); var cell_1 = require("./cell"); var edge_1 = require("./edge"); var node_1 = require("./node"); var collection_1 = require("./collection"); var Model = /** @class */ (function (_super) { __extends(Model, _super); function Model(cells) { if (cells === void 0) { cells = []; } var _this = _super.call(this) || this; _this.batches = {}; _this.addings = new WeakMap(); _this.nodes = {}; _this.edges = {}; _this.outgoings = {}; _this.incomings = {}; _this.collection = new collection_1.Collection(cells); _this.setup(); return _this; } Object.defineProperty(Model.prototype, Symbol.toStringTag, { get: function () { return Model.toStringTag; }, enumerable: false, configurable: true }); Model.prototype.notify = function (name, args) { this.trigger(name, args); var graph = this.graph; if (graph) { if (name === 'sorted' || name === 'reseted' || name === 'updated') { graph.trigger("model:" + name, args); } else { graph.trigger(name, args); } } return this; }; Model.prototype.setup = function () { var _this = this; var collection = this.collection; collection.on('sorted', function () { return _this.notify('sorted', null); }); collection.on('updated', function (args) { return _this.notify('updated', args); }); collection.on('cell:change:zIndex', function () { return _this.sortOnChangeZ(); }); collection.on('added', function (_a) { var cell = _a.cell; _this.onCellAdded(cell); }); collection.on('removed', function (args) { var cell = args.cell; _this.onCellRemoved(cell, args.options); // Should trigger remove-event manually after cell was removed. _this.notify('cell:removed', args); if (cell.isNode()) { _this.notify('node:removed', __assign(__assign({}, args), { node: cell })); } else if (cell.isEdge()) { _this.notify('edge:removed', __assign(__assign({}, args), { edge: cell })); } }); collection.on('reseted', function (args) { _this.onReset(args.current); _this.notify('reseted', args); }); collection.on('edge:change:source', function (_a) { var edge = _a.edge; return _this.onEdgeTerminalChanged(edge, 'source'); }); collection.on('edge:change:target', function (_a) { var edge = _a.edge; _this.onEdgeTerminalChanged(edge, 'target'); }); }; Model.prototype.sortOnChangeZ = function () { this.collection.sort(); }; Model.prototype.onCellAdded = function (cell) { var cellId = cell.id; if (cell.isEdge()) { // Auto update edge's parent cell.updateParent(); this.edges[cellId] = true; this.onEdgeTerminalChanged(cell, 'source'); this.onEdgeTerminalChanged(cell, 'target'); } else { this.nodes[cellId] = true; } }; Model.prototype.onCellRemoved = function (cell, options) { var cellId = cell.id; if (cell.isEdge()) { delete this.edges[cellId]; var source = cell.getSource(); var target = cell.getTarget(); if (source && source.cell) { var cache = this.outgoings[source.cell]; var index = cache ? cache.indexOf(cellId) : -1; if (index >= 0) { cache.splice(index, 1); if (cache.length === 0) { delete this.outgoings[source.cell]; } } } if (target && target.cell) { var cache = this.incomings[target.cell]; var index = cache ? cache.indexOf(cellId) : -1; if (index >= 0) { cache.splice(index, 1); if (cache.length === 0) { delete this.incomings[target.cell]; } } } } else { delete this.nodes[cellId]; } if (!options.clear) { if (options.disconnectEdges) { this.disconnectConnectedEdges(cell, options); } else { this.removeConnectedEdges(cell, options); } } if (cell.model === this) { cell.model = null; } }; Model.prototype.onReset = function (cells) { var _this = this; this.nodes = {}; this.edges = {}; this.outgoings = {}; this.incomings = {}; cells.forEach(function (cell) { return _this.onCellAdded(cell); }); }; Model.prototype.onEdgeTerminalChanged = function (edge, type) { var ref = type === 'source' ? this.outgoings : this.incomings; var prev = edge.previous(type); if (prev && prev.cell) { var cache = ref[prev.cell]; var index = cache ? cache.indexOf(edge.id) : -1; if (index >= 0) { cache.splice(index, 1); if (cache.length === 0) { delete ref[prev.cell]; } } } var terminal = edge.getTerminal(type); if (terminal && terminal.cell) { var cache = ref[terminal.cell] || []; var index = cache.indexOf(edge.id); if (index === -1) { cache.push(edge.id); } ref[terminal.cell] = cache; } }; Model.prototype.prepareCell = function (cell, options) { if (!cell.model && (!options || !options.dryrun)) { cell.model = this; } if (cell.zIndex == null) { cell.setZIndex(this.getMaxZIndex() + 1, { silent: true }); } return cell; }; Model.prototype.resetCells = function (cells, options) { var _this = this; if (options === void 0) { options = {}; } // Do not update model at this time. Because if we just update the graph // with the same json-data, the edge will reference to the old nodes. cells.map(function (cell) { return _this.prepareCell(cell, __assign(__assign({}, options), { dryrun: true })); }); this.collection.reset(cells, options); // Update model and trigger edge update it's references cells.map(function (cell) { return _this.prepareCell(cell, { options: options }); }); return this; }; Model.prototype.clear = function (options) { if (options === void 0) { options = {}; } var raw = this.getCells(); if (raw.length === 0) { return this; } var localOptions = __assign(__assign({}, options), { clear: true }); this.batchUpdate('clear', function () { // The nodes come after the edges. var cells = raw.sort(function (a, b) { var v1 = a.isEdge() ? 1 : 2; var v2 = b.isEdge() ? 1 : 2; return v1 - v2; }); while (cells.length > 0) { // Note that all the edges are removed first, so it's safe to // remove the nodes without removing the connected edges first. var cell = cells.shift(); if (cell) { cell.remove(localOptions); } } }, localOptions); return this; }; Model.prototype.addNode = function (metadata, options) { if (options === void 0) { options = {}; } var node = node_1.Node.isNode(metadata) ? metadata : this.createNode(metadata); this.addCell(node, options); return node; }; Model.prototype.createNode = function (metadata) { return node_1.Node.create(metadata); }; Model.prototype.addEdge = function (metadata, options) { if (options === void 0) { options = {}; } var edge = edge_1.Edge.isEdge(metadata) ? metadata : this.createEdge(metadata); this.addCell(edge, options); return edge; }; Model.prototype.createEdge = function (metadata) { return edge_1.Edge.create(metadata); }; Model.prototype.addCell = function (cell, options) { var _this = this; if (options === void 0) { options = {}; } if (Array.isArray(cell)) { return this.addCells(cell, options); } if (!this.collection.has(cell) && !this.addings.has(cell)) { this.addings.set(cell, true); this.collection.add(this.prepareCell(cell, options), options); cell.eachChild(function (child) { return _this.addCell(child, options); }); this.addings.delete(cell); } return this; }; Model.prototype.addCells = function (cells, options) { var _this = this; if (options === void 0) { options = {}; } var count = cells.length; if (count === 0) { return this; } var localOptions = __assign(__assign({}, options), { position: count - 1, maxPosition: count - 1 }); this.startBatch('add', __assign(__assign({}, localOptions), { cells: cells })); cells.forEach(function (cell) { _this.addCell(cell, localOptions); localOptions.position -= 1; }); this.stopBatch('add', __assign(__assign({}, localOptions), { cells: cells })); return this; }; Model.prototype.removeCell = function (obj, options) { if (options === void 0) { options = {}; } var cell = typeof obj === 'string' ? this.getCell(obj) : obj; if (cell && this.has(cell)) { return this.collection.remove(cell, options); } return null; }; Model.prototype.removeCells = function (cells, options) { var _this = this; if (options === void 0) { options = {}; } if (cells.length) { return this.batchUpdate('remove', function () { return cells.map(function (cell) { return _this.removeCell(cell, options); }); }); } return []; }; Model.prototype.removeConnectedEdges = function (cell, options) { if (options === void 0) { options = {}; } var edges = this.getConnectedEdges(cell); edges.forEach(function (edge) { edge.remove(options); }); return edges; }; Model.prototype.disconnectConnectedEdges = function (cell, options) { if (options === void 0) { options = {}; } var cellId = typeof cell === 'string' ? cell : cell.id; this.getConnectedEdges(cell).forEach(function (edge) { var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (sourceCell && sourceCell.id === cellId) { edge.setSource({ x: 0, y: 0 }, options); } if (targetCell && targetCell.id === cellId) { edge.setTarget({ x: 0, y: 0 }, options); } }); }; Model.prototype.has = function (obj) { return this.collection.has(obj); }; Model.prototype.total = function () { return this.collection.length; }; Model.prototype.indexOf = function (cell) { return this.collection.indexOf(cell); }; /** * Returns a cell from the graph by its id. */ Model.prototype.getCell = function (id) { return this.collection.get(id); }; /** * Returns all the nodes and edges in the graph. */ Model.prototype.getCells = function () { return this.collection.toArray(); }; /** * Returns the first cell (node or edge) in the graph. The first cell is * defined as the cell with the lowest `zIndex`. */ Model.prototype.getFirstCell = function () { return this.collection.first(); }; /** * Returns the last cell (node or edge) in the graph. The last cell is * defined as the cell with the highest `zIndex`. */ Model.prototype.getLastCell = function () { return this.collection.last(); }; /** * Returns the lowest `zIndex` value in the graph. */ Model.prototype.getMinZIndex = function () { var first = this.collection.first(); return first ? first.getZIndex() || 0 : 0; }; /** * Returns the highest `zIndex` value in the graph. */ Model.prototype.getMaxZIndex = function () { var last = this.collection.last(); return last ? last.getZIndex() || 0 : 0; }; Model.prototype.getCellsFromCache = function (cache) { var _this = this; return cache ? Object.keys(cache) .map(function (id) { return _this.getCell(id); }) .filter(function (cell) { return cell != null; }) : []; }; /** * Returns all the nodes in the graph. */ Model.prototype.getNodes = function () { return this.getCellsFromCache(this.nodes); }; /** * Returns all the edges in the graph. */ Model.prototype.getEdges = function () { return this.getCellsFromCache(this.edges); }; /** * Returns all outgoing edges for the node. */ Model.prototype.getOutgoingEdges = function (cell) { var _this = this; var cellId = typeof cell === 'string' ? cell : cell.id; var cellIds = this.outgoings[cellId]; return cellIds ? cellIds .map(function (id) { return _this.getCell(id); }) .filter(function (cell) { return cell && cell.isEdge(); }) : null; }; /** * Returns all incoming edges for the node. */ Model.prototype.getIncomingEdges = function (cell) { var _this = this; var cellId = typeof cell === 'string' ? cell : cell.id; var cellIds = this.incomings[cellId]; return cellIds ? cellIds .map(function (id) { return _this.getCell(id); }) .filter(function (cell) { return cell && cell.isEdge(); }) : null; }; /** * Returns edges connected with cell. */ Model.prototype.getConnectedEdges = function (cell, options) { var _this = this; if (options === void 0) { options = {}; } var result = []; var node = typeof cell === 'string' ? this.getCell(cell) : cell; if (node == null) { return result; } var cache = {}; var indirect = options.indirect; var incoming = options.incoming; var outgoing = options.outgoing; if (incoming == null && outgoing == null) { incoming = outgoing = true; } var collect = function (cell, isOutgoing) { var edges = isOutgoing ? _this.getOutgoingEdges(cell) : _this.getIncomingEdges(cell); if (edges != null) { edges.forEach(function (edge) { if (cache[edge.id]) { return; } result.push(edge); cache[edge.id] = true; if (indirect) { if (incoming) { collect(edge, false); } if (outgoing) { collect(edge, true); } } }); } if (indirect && cell.isEdge()) { var terminal = isOutgoing ? cell.getTargetCell() : cell.getSourceCell(); if (terminal && terminal.isEdge()) { if (!cache[terminal.id]) { result.push(terminal); collect(terminal, isOutgoing); } } } }; if (outgoing) { collect(node, true); } if (incoming) { collect(node, false); } if (options.deep) { var descendants = node.getDescendants({ deep: true }); var embedsCache_1 = {}; descendants.forEach(function (cell) { if (cell.isNode()) { embedsCache_1[cell.id] = true; } }); var collectSub_1 = function (cell, isOutgoing) { var edges = isOutgoing ? _this.getOutgoingEdges(cell.id) : _this.getIncomingEdges(cell.id); if (edges != null) { edges.forEach(function (edge) { if (!cache[edge.id]) { var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (!options.enclosed && sourceCell && embedsCache_1[sourceCell.id] && targetCell && embedsCache_1[targetCell.id]) { return; } result.push(edge); cache[edge.id] = true; } }); } }; descendants.forEach(function (cell) { if (cell.isEdge()) { return; } if (outgoing) { collectSub_1(cell, true); } if (incoming) { collectSub_1(cell, false); } }); } return result; }; Model.prototype.isBoundary = function (cell, isOrigin) { var node = typeof cell === 'string' ? this.getCell(cell) : cell; var arr = isOrigin ? this.getIncomingEdges(node) : this.getOutgoingEdges(node); return arr == null || arr.length === 0; }; Model.prototype.getBoundaryNodes = function (isOrigin) { var _this = this; var result = []; Object.keys(this.nodes).forEach(function (nodeId) { if (_this.isBoundary(nodeId, isOrigin)) { var node = _this.getCell(nodeId); if (node) { result.push(node); } } }); return result; }; /** * Returns an array of all the roots of the graph. */ Model.prototype.getRoots = function () { return this.getBoundaryNodes(true); }; /** * Returns an array of all the leafs of the graph. */ Model.prototype.getLeafs = function () { return this.getBoundaryNodes(false); }; /** * Returns `true` if the node is a root node, i.e. there is no edges * coming to the node. */ Model.prototype.isRoot = function (cell) { return this.isBoundary(cell, true); }; /** * Returns `true` if the node is a leaf node, i.e. there is no edges * going out from the node. */ Model.prototype.isLeaf = function (cell) { return this.isBoundary(cell, false); }; /** * Returns all the neighbors of node in the graph. Neighbors are all * the nodes connected to node via either incoming or outgoing edge. */ Model.prototype.getNeighbors = function (cell, options) { if (options === void 0) { options = {}; } var incoming = options.incoming; var outgoing = options.outgoing; if (incoming == null && outgoing == null) { incoming = outgoing = true; } var edges = this.getConnectedEdges(cell, options); var map = edges.reduce(function (memo, edge) { var hasLoop = edge.hasLoop(options); var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (incoming && sourceCell && sourceCell.isNode() && !memo[sourceCell.id]) { if (hasLoop || (sourceCell !== cell && (!options.deep || !sourceCell.isDescendantOf(cell)))) { memo[sourceCell.id] = sourceCell; } } if (outgoing && targetCell && targetCell.isNode() && !memo[targetCell.id]) { if (hasLoop || (targetCell !== cell && (!options.deep || !targetCell.isDescendantOf(cell)))) { memo[targetCell.id] = targetCell; } } return memo; }, {}); if (cell.isEdge()) { if (incoming) { var sourceCell = cell.getSourceCell(); if (sourceCell && sourceCell.isNode() && !map[sourceCell.id]) { map[sourceCell.id] = sourceCell; } } if (outgoing) { var targetCell = cell.getTargetCell(); if (targetCell && targetCell.isNode() && !map[targetCell.id]) { map[targetCell.id] = targetCell; } } } return Object.keys(map).map(function (id) { return map[id]; }); }; /** * Returns `true` if `cell2` is a neighbor of `cell1`. */ Model.prototype.isNeighbor = function (cell1, cell2, options) { if (options === void 0) { options = {}; } var incoming = options.incoming; var outgoing = options.outgoing; if (incoming == null && outgoing == null) { incoming = outgoing = true; } return this.getConnectedEdges(cell1, options).some(function (edge) { var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (incoming && sourceCell && sourceCell.id === cell2.id) { return true; } if (outgoing && targetCell && targetCell.id === cell2.id) { return true; } return false; }); }; Model.prototype.getSuccessors = function (cell, options) { var _this = this; if (options === void 0) { options = {}; } var successors = []; this.search(cell, function (curr, distance) { if (curr !== cell && _this.matchDistance(distance, options.distance)) { successors.push(curr); } }, __assign(__assign({}, options), { outgoing: true })); return successors; }; /** * Returns `true` if `cell2` is a successor of `cell1`. */ Model.prototype.isSuccessor = function (cell1, cell2, options) { var _this = this; if (options === void 0) { options = {}; } var result = false; this.search(cell1, function (curr, distance) { if (curr === cell2 && curr !== cell1 && _this.matchDistance(distance, options.distance)) { result = true; return false; } }, __assign(__assign({}, options), { outgoing: true })); return result; }; Model.prototype.getPredecessors = function (cell, options) { var _this = this; if (options === void 0) { options = {}; } var predecessors = []; this.search(cell, function (curr, distance) { if (curr !== cell && _this.matchDistance(distance, options.distance)) { predecessors.push(curr); } }, __assign(__assign({}, options), { incoming: true })); return predecessors; }; /** * Returns `true` if `cell2` is a predecessor of `cell1`. */ Model.prototype.isPredecessor = function (cell1, cell2, options) { var _this = this; if (options === void 0) { options = {}; } var result = false; this.search(cell1, function (curr, distance) { if (curr === cell2 && curr !== cell1 && _this.matchDistance(distance, options.distance)) { result = true; return false; } }, __assign(__assign({}, options), { incoming: true })); return result; }; Model.prototype.matchDistance = function (distance, preset) { if (preset == null) { return true; } if (typeof preset === 'function') { return preset(distance); } if (Array.isArray(preset) && preset.includes(distance)) { return true; } return distance === preset; }; /** * Returns the common ancestor of the passed cells. */ Model.prototype.getCommonAncestor = function () { var cells = []; for (var _i = 0; _i < arguments.length; _i++) { cells[_i] = arguments[_i]; } var arr = []; cells.forEach(function (item) { if (item) { if (Array.isArray(item)) { arr.push.apply(arr, item); } else { arr.push(item); } } }); return cell_1.Cell.getCommonAncestor.apply(cell_1.Cell, arr); }; /** * Returns an array of cells that result from finding nodes/edges that * are connected to any of the cells in the cells array. This function * loops over cells and if the current cell is a edge, it collects its * source/target nodes; if it is an node, it collects its incoming and * outgoing edges if both the edge terminal (source/target) are in the * cells array. */ Model.prototype.getSubGraph = function (cells, options) { var _this = this; if (options === void 0) { options = {}; } var subgraph = []; var cache = {}; var nodes = []; var edges = []; var collect = function (cell) { if (!cache[cell.id]) { subgraph.push(cell); cache[cell.id] = cell; if (cell.isEdge()) { edges.push(cell); } if (cell.isNode()) { nodes.push(cell); } } }; cells.forEach(function (cell) { collect(cell); if (options.deep) { var descendants = cell.getDescendants({ deep: true }); descendants.forEach(function (descendant) { return collect(descendant); }); } }); edges.forEach(function (edge) { // For edges, include their source & target var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (sourceCell && !cache[sourceCell.id]) { subgraph.push(sourceCell); cache[sourceCell.id] = sourceCell; if (sourceCell.isNode()) { nodes.push(sourceCell); } } if (targetCell && !cache[targetCell.id]) { subgraph.push(targetCell); cache[targetCell.id] = targetCell; if (targetCell.isNode()) { nodes.push(targetCell); } } }); nodes.forEach(function (node) { // For nodes, include their connected edges if their source/target // is in the subgraph. var edges = _this.getConnectedEdges(node, options); edges.forEach(function (edge) { var sourceCell = edge.getSourceCell(); var targetCell = edge.getTargetCell(); if (!cache[edge.id] && sourceCell && cache[sourceCell.id] && targetCell && cache[targetCell.id]) { subgraph.push(edge); cache[edge.id] = edge; } }); }); return subgraph; }; /** * Clones the whole subgraph (including all the connected links whose * source/target is in the subgraph). If `options.deep` is `true`, also * take into account all the embedded cells of all the subgraph cells. * * Returns a map of the form: { [original cell ID]: [clone] }. */ Model.prototype.cloneSubGraph = function (cells, options) { if (options === void 0) { options = {}; } var subgraph = this.getSubGraph(cells, options); return this.cloneCells(subgraph); }; Model.prototype.cloneCells = function (cells) { return cell_1.Cell.cloneCells(cells); }; Model.prototype.getNodesFromPoint = function (x, y) { var p = typeof x === 'number' ? { x: x, y: y || 0 } : x; return this.getNodes().filter(function (node) { return node.getBBox().containsPoint(p); }); }; Model.prototype.getNodesInArea = function (x, y, w, h, options) { var rect = typeof x === 'number' ? new geometry_1.Rectangle(x, y, w, h) : geometry_1.Rectangle.create(x); var opts = typeof x === 'number' ? options : y; var strict = opts && opts.strict; return this.getNodes().filter(function (node) { var bbox = node.getBBox(); return strict ? rect.containsRect(bbox) : rect.isIntersectWithRect(bbox); }); }; Model.prototype.getEdgesInArea = function (x, y, w, h, options) { var rect = typeof x === 'number' ? new geometry_1.Rectangle(x, y, w, h) : geometry_1.Rectangle.create(x); var opts = typeof x === 'number' ? options : y; var strict = opts && opts.strict; return this.getEdges().filter(function (edge) { var bbox = edge.getBBox(); return strict ? rect.containsRect(bbox) : rect.isIntersectWithRect(bbox); }); }; Model.prototype.getNodesUnderNode = function (node, options) { if (options === void 0) { options = {}; } var bbox = node.getBBox(); var nodes = options.by == null || options.by === 'bbox' ? this.getNodesInArea(bbox) : this.getNodesFromPoint(bbox[options.by]); return nodes.filter(function (curr) { return node.id !== curr.id && !curr.isDescendantOf(node); }); }; /** * Returns the bounding box that surrounds all cells in the graph. */ Model.prototype.getAllCellsBBox = function () { return this.getCellsBBox(this.getCells()); }; /** * Returns the bounding box that surrounds all the given cells. */ Model.prototype.getCellsBBox = function (cells, options) { if (options === void 0) { options = {}; } return cell_1.Cell.getCellsBBox(cells, options); }; // #region search Model.prototype.search = function (cell, iterator, options) { if (options === void 0) { options = {}; } if (options.breadthFirst) { this.breadthFirstSearch(cell, iterator, options); } else { this.depthFirstSearch(cell, iterator, options); } }; Model.prototype.breadthFirstSearch = function (cell, iterator, options) { if (options === void 0) { options = {}; } var queue = []; var visited = {}; var distance = {}; queue.push(cell); distance[cell.id] = 0; var _loop_1 = function () { var next = queue.shift(); if (next == null || visited[next.id]) { return "continue"; } visited[next.id] = true; if (util_1.FunctionExt.call(iterator, this_1, next, distance[next.id]) === false) { return "continue"; } var neighbors = this_1.getNeighbors(next, options); neighbors.forEach(function (neighbor) { distance[neighbor.id] = distance[next.id] + 1; queue.push(neighbor); }); }; var this_1 = this; while (queue.length > 0) { _loop_1(); } }; Model.prototype.depthFirstSearch = function (cell, iterator, options) { if (options === void 0) { options = {}; } var queue = []; var visited = {}; var distance = {}; queue.push(cell); distance[cell.id] = 0; var _loop_2 = function () { var next = queue.pop(); if (next == null || visited[next.id]) { return "continue"; } visited[next.id] = true; if (util_1.FunctionExt.call(iterator, this_2, next, distance[next.id]) === false) { return "continue"; } var neighbors = this_2.getNeighbors(next, options); var lastIndex = queue.length; neighbors.forEach(function (neighbor) { distance[neighbor.id] = distance[next.id] + 1; queue.splice(lastIndex, 0, neighbor); }); }; var this_2 = this; while (queue.length > 0) { _loop_2(); } }; // #endregion // #region shortest path /** * * Returns an array of IDs of nodes on the shortest * path between source and target. */ Model.prototype.getShortestPath = function (source, target, options) { if (options === void 0) { options = {}; } var adjacencyList = {}; this.getEdges().forEach(function (edge) { var sourceId = edge.getSourceCellId(); var targetId = edge.getTargetCellId(); if (sourceId && targetId) { if (!adjacencyList[sourceId]) { adjacencyList[sourceId] = []; } if (!adjacencyList[targetId]) { adjacencyList[targetId] = []; } adjacencyList[sourceId].push(targetId); if (!options.directed) { adjacencyList[targetId].push(sourceId); } } }); var sourceId = typeof source === 'string' ? source : source.id; var previous = common_1.Dijkstra.run(adjacencyList, sourceId, options.weight); var path = []; var targetId = typeof target === 'string' ? target : target.id; if (previous[targetId]) { path.push(targetId); } while ((targetId = previous[targetId])) { path.unshift(targetId); } return path; }; // #endregion // #region transform /** * Translate all cells in the graph by `tx` and `ty` pixels. */ Model.prototype.translate = function (tx, ty, options) { this.getCells() .filter(function (cell) { return !cell.hasParent(); }) .forEach(function (cell) { return cell.translate(tx, ty, options); }); return this; }; Model.prototype.resize = function (width, height, options) { return this.resizeCells(width, height, this.getCells(), options); }; Model.prototype.resizeCells = function (width, height, cells, options) { if (options === void 0) { options = {}; } var bbox = this.getCellsBBox(cells); if (bbox) { var sx_1 = Math.max(width / bbox.width, 0); var sy_1 = Math.max(height / bbox.height, 0); var origin_1 = bbox.getOrigin(); cells.forEach(function (cell) { return cell.scale(sx_1, sy_1, origin_1, options); }); } return this; }; // #endregion // #region serialize/deserialize Model.prototype.toJSON = function (options) { if (options === void 0) { options = {}; } return Model.toJSON(this.getCells(), options); }; Model.prototype.parseJSON = function (data) { return Model.fromJSON(data); }; Model.prototype.fromJSON = function (data, options) { if (options === void 0) { options = {}; } var cells = this.parseJSON(data); this.resetCells(cells, options); return this; }; // #endregion // #region batch Model.prototype.startBatch = function (name, data) { if (data === void 0) { data = {}; } this.batches[name] = (this.batches[name] || 0) + 1; this.notify('batch:start', { name: name, data: data }); return this; }; Model.prototype.stopBatch = function (name, data) { if (data === void 0) { data = {}; } this.batches[name] = (this.batches[name] || 0) - 1; this.notify('batch:stop', { name: name, data: data }); return this; }; Model.prototype.batchUpdate = function (name, execute, data) { if (data === void 0) { data = {}; } this.startBatch(name, data); var result = execute(); this.stopBatch(name, data); return result; }; Model.prototype.hasActiveBatch = function (name) { var _this = this; if (name === void 0) { name = Object.keys(this.batches); } var names = Array.isArray(name) ? name : [name]; return names.some(function (batch) { return _this.batches[batch] > 0; }); }; return Model; }(common_1.Basecoat)); exports.Model = Model; (function (Model) { Model.toStringTag = "X6." + Model.name; function isModel(instance) { if (instance == null) { return false; } if (instance instanceof Model) { return true; } var tag = instance[Symbol.toStringTag]; var model = instance; if ((tag == null || tag === Model.toStringTag) && typeof model.addNode === 'function' && typeof model.addEdge === 'function' && model.collection != null) { return true; } return false; } Model.isModel = isModel; })(Model = exports.Model || (exports.Model = {})); exports.Model = Model; (function (Model) { function toJSON(cells, options) { if (options === void 0) { options = {}; } return { cells: cells.map(function (cell) { return cell.toJSON(options); }), }; } Model.toJSON = toJSON; function fromJSON(data) { var cells = []; if (Array.isArray(data)) { cells.push.apply(cells, data); } else { if (data.cells) { cells.push.apply(cells, data.cells); } if (data.nodes) { data.nodes.forEach(function (node) { if (node.shape == null) { node.shape = 'rect'; } cells.push(node); }); } if (data.edges) { data.edges.forEach(function (edge) { if (edge.shape == null) { edge.shape = 'edge'; } cells.push(edge); }); } } return cells.map(function (cell) { var type = cell.shape; if (type) { if (node_1.Node.registry.exist(type)) { return node_1.Node.create(cell); } if (edge_1.Edge.registry.exist(type)) { return edge_1.Edge.create(cell); } } throw new Error('The `shape` should be specipied when creating a node/edge instance'); }); } Model.fromJSON = fromJSON; })(Model = exports.Model || (exports.Model = {})); exports.Model = Model; //# sourceMappingURL=model.js.map