UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

1,005 lines 40.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.NodeView = void 0; var global_1 = require("../global"); var util_1 = require("../util"); var geometry_1 = require("../geometry"); var cell_1 = require("../model/cell"); var cell_2 = require("./cell"); var markup_1 = require("./markup"); var NodeView = /** @class */ (function (_super) { __extends(NodeView, _super); function NodeView() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.scalableNode = null; _this.rotatableNode = null; _this.scalableSelector = 'scalable'; _this.rotatableSelector = 'rotatable'; _this.defaultPortMarkup = markup_1.Markup.getPortMarkup(); _this.defaultPortLabelMarkup = markup_1.Markup.getPortLabelMarkup(); _this.defaultPortContainerMarkup = markup_1.Markup.getPortContainerMarkup(); _this.portsCache = {}; return _this; // #endregion } Object.defineProperty(NodeView.prototype, Symbol.toStringTag, { get: function () { return NodeView.toStringTag; }, enumerable: false, configurable: true }); NodeView.prototype.getContainerClassName = function () { var classList = [ _super.prototype.getContainerClassName.call(this), this.prefixClassName('node'), ]; if (!this.can('nodeMovable')) { classList.push(this.prefixClassName('node-immovable')); } return classList.join(' '); }; NodeView.prototype.updateClassName = function (e) { var target = e.target; if (target.hasAttribute('magnet')) { // port var className = this.prefixClassName('port-unconnectable'); if (this.can('magnetConnectable')) { util_1.Dom.removeClass(target, className); } else { util_1.Dom.addClass(target, className); } } else { // node var className = this.prefixClassName('node-immovable'); if (this.can('nodeMovable')) { this.removeClass(className); } else { this.addClass(className); } } }; NodeView.prototype.isNodeView = function () { return true; }; NodeView.prototype.confirmUpdate = function (flag, options) { var _this = this; if (options === void 0) { options = {}; } var ret = flag; if (this.hasAction(ret, 'ports')) { this.removePorts(); this.cleanPortsCache(); } if (this.hasAction(ret, 'render')) { this.render(); ret = this.removeAction(ret, [ 'render', 'update', 'resize', 'translate', 'rotate', 'ports', 'tools', ]); } else { ret = this.handleAction(ret, 'resize', function () { return _this.resize(options); }, 'update'); ret = this.handleAction(ret, 'update', function () { return _this.update(); }, // `update()` will render ports when useCSSSelectors are enabled global_1.Config.useCSSSelector ? 'ports' : null); ret = this.handleAction(ret, 'translate', function () { return _this.translate(); }); ret = this.handleAction(ret, 'rotate', function () { return _this.rotate(); }); ret = this.handleAction(ret, 'ports', function () { return _this.renderPorts(); }); ret = this.handleAction(ret, 'tools', function () { return _this.renderTools(); }); } return ret; }; NodeView.prototype.update = function (partialAttrs) { this.cleanCache(); // When CSS selector strings are used, make sure no rule matches port nodes. if (global_1.Config.useCSSSelector) { this.removePorts(); } var node = this.cell; var size = node.getSize(); var attrs = node.getAttrs(); this.updateAttrs(this.container, attrs, { attrs: partialAttrs === attrs ? null : partialAttrs, rootBBox: new geometry_1.Rectangle(0, 0, size.width, size.height), selectors: this.selectors, scalableNode: this.scalableNode, rotatableNode: this.rotatableNode, }); if (global_1.Config.useCSSSelector) { this.renderPorts(); } }; NodeView.prototype.renderMarkup = function () { var markup = this.cell.markup; if (markup) { if (typeof markup === 'string') { return this.renderStringMarkup(markup); } return this.renderJSONMarkup(markup); } throw new TypeError('Invalid node markup.'); }; NodeView.prototype.renderJSONMarkup = function (markup) { var ret = this.parseJSONMarkup(markup, this.container); var one = function (elems) { return Array.isArray(elems) ? elems[0] : elems; }; this.selectors = ret.selectors; this.rotatableNode = one(this.selectors[this.rotatableSelector]); this.scalableNode = one(this.selectors[this.scalableSelector]); this.container.appendChild(ret.fragment); }; NodeView.prototype.renderStringMarkup = function (markup) { util_1.Dom.append(this.container, util_1.Vector.toNodes(util_1.Vector.createVectors(markup))); this.rotatableNode = util_1.Dom.findOne(this.container, "." + this.rotatableSelector); this.scalableNode = util_1.Dom.findOne(this.container, "." + this.scalableSelector); this.selectors = {}; if (this.rootSelector) { this.selectors[this.rootSelector] = this.container; } }; NodeView.prototype.render = function () { this.empty(); this.renderMarkup(); if (this.scalableNode) { // Double update is necessary for elements with the scalable group only // Note the `resize()` triggers the other `update`. this.update(); } this.resize(); if (this.rotatableNode) { this.rotate(); this.translate(); } else { this.updateTransform(); } if (!global_1.Config.useCSSSelector) { this.renderPorts(); } this.renderTools(); return this; }; NodeView.prototype.resize = function (opt) { if (opt === void 0) { opt = {}; } if (this.scalableNode) { return this.updateSize(opt); } if (this.cell.getAngle()) { this.rotate(); } this.update(); }; NodeView.prototype.translate = function () { if (this.rotatableNode) { return this.updateTranslation(); } this.updateTransform(); }; NodeView.prototype.rotate = function () { if (this.rotatableNode) { this.updateRotation(); // It's necessary to call the update for the nodes outside // the rotatable group referencing nodes inside the group this.update(); return; } this.updateTransform(); }; NodeView.prototype.getTranslationString = function () { var position = this.cell.getPosition(); return "translate(" + position.x + "," + position.y + ")"; }; NodeView.prototype.getRotationString = function () { var angle = this.cell.getAngle(); if (angle) { var size = this.cell.getSize(); return "rotate(" + angle + "," + size.width / 2 + "," + size.height / 2 + ")"; } }; NodeView.prototype.updateTransform = function () { var transform = this.getTranslationString(); var rot = this.getRotationString(); if (rot) { transform += " " + rot; } this.container.setAttribute('transform', transform); }; NodeView.prototype.updateRotation = function () { if (this.rotatableNode != null) { var transform = this.getRotationString(); if (transform != null) { this.rotatableNode.setAttribute('transform', transform); } else { this.rotatableNode.removeAttribute('transform'); } } }; NodeView.prototype.updateTranslation = function () { this.container.setAttribute('transform', this.getTranslationString()); }; NodeView.prototype.updateSize = function (opt) { if (opt === void 0) { opt = {}; } var cell = this.cell; var size = cell.getSize(); var angle = cell.getAngle(); var scalableNode = this.scalableNode; // Getting scalable group's bbox. // Due to a bug in webkit's native SVG .getBBox implementation, the // bbox of groups with path children includes the paths' control points. // To work around the issue, we need to check whether there are any path // elements inside the scalable group. var recursive = false; if (scalableNode.getElementsByTagName('path').length > 0) { // If scalable has at least one descendant that is a path, we need // toswitch to recursive bbox calculation. Otherwise, group bbox // calculation works and so we can use the (faster) native function. recursive = true; } var scalableBBox = util_1.Dom.getBBox(scalableNode, { recursive: recursive }); // Make sure `scalableBbox.width` and `scalableBbox.height` are not zero // which can happen if the element does not have any content. var sx = size.width / (scalableBBox.width || 1); var sy = size.height / (scalableBBox.height || 1); scalableNode.setAttribute('transform', "scale(" + sx + "," + sy + ")"); // Now the interesting part. The goal is to be able to store the object geometry via just `x`, `y`, `angle`, `width` and `height` // Order of transformations is significant but we want to reconstruct the object always in the order: // resize(), rotate(), translate() no matter of how the object was transformed. For that to work, // we must adjust the `x` and `y` coordinates of the object whenever we resize it (because the origin of the // rotation changes). The new `x` and `y` coordinates are computed by canceling the previous rotation // around the center of the resized object (which is a different origin then the origin of the previous rotation) // and getting the top-left corner of the resulting object. Then we clean up the rotation back to what it originally was. // Cancel the rotation but now around a different origin, which is the center of the scaled object. var rotatableNode = this.rotatableNode; if (rotatableNode != null) { var transform = rotatableNode.getAttribute('transform'); if (transform) { rotatableNode.setAttribute('transform', transform + " rotate(" + -angle + "," + size.width / 2 + "," + size.height / 2 + ")"); var rotatableBBox = util_1.Dom.getBBox(scalableNode, { target: this.graph.view.stage, }); // Store new x, y and perform rotate() again against the new rotation origin. cell.prop('position', { x: rotatableBBox.x, y: rotatableBBox.y }, __assign({ updated: true }, opt)); this.translate(); this.rotate(); } } // Update must always be called on non-rotated element. Otherwise, // relative positioning would work with wrong (rotated) bounding boxes. this.update(); }; // #region ports NodeView.prototype.findPortElem = function (portId, selector) { var cache = portId ? this.portsCache[portId] : null; if (!cache) { return null; } var portRoot = cache.portContentElement; var portSelectors = cache.portContentSelectors || {}; return this.findOne(selector, portRoot, portSelectors); }; NodeView.prototype.initializePorts = function () { this.cleanPortsCache(); }; NodeView.prototype.refreshPorts = function () { this.removePorts(); this.cleanPortsCache(); this.renderPorts(); }; NodeView.prototype.cleanPortsCache = function () { this.portsCache = {}; }; NodeView.prototype.removePorts = function () { var _this = this; Object.keys(this.portsCache).forEach(function (portId) { var cached = _this.portsCache[portId]; util_1.Dom.remove(cached.portElement); }); }; NodeView.prototype.renderPorts = function () { var _this = this; var container = this.getPortsContainer(); // References to rendered elements without z-index var references = []; container.childNodes.forEach(function (child) { references.push(child); }); var portsGropsByZ = util_1.ArrayExt.groupBy(this.cell.getParsedPorts(), 'zIndex'); var autoZIndexKey = 'auto'; // render non-z first if (portsGropsByZ[autoZIndexKey]) { portsGropsByZ[autoZIndexKey].forEach(function (port) { var portElement = _this.getPortElement(port); container.append(portElement); references.push(portElement); }); } Object.keys(portsGropsByZ).forEach(function (key) { if (key !== autoZIndexKey) { var zIndex = parseInt(key, 10); _this.appendPorts(portsGropsByZ[key], zIndex, references); } }); this.updatePorts(); }; NodeView.prototype.getPortsContainer = function () { return this.rotatableNode || this.container; }; NodeView.prototype.appendPorts = function (ports, zIndex, refs) { var _this = this; var elems = ports.map(function (p) { return _this.getPortElement(p); }); if (refs[zIndex] || zIndex < 0) { util_1.Dom.before(refs[Math.max(zIndex, 0)], elems); } else { util_1.Dom.append(this.getPortsContainer(), elems); } }; NodeView.prototype.getPortElement = function (port) { var cached = this.portsCache[port.id]; if (cached) { return cached.portElement; } return this.createPortElement(port); }; NodeView.prototype.createPortElement = function (port) { var renderResult = markup_1.Markup.renderMarkup(this.getPortContainerMarkup()); var portElement = renderResult.elem; if (portElement == null) { throw new Error('Invalid port container markup.'); } renderResult = markup_1.Markup.renderMarkup(this.getPortMarkup(port)); var portContentElement = renderResult.elem; var portContentSelectors = renderResult.selectors; if (portContentElement == null) { throw new Error('Invalid port markup.'); } this.setAttrs({ port: port.id, 'port-group': port.group, }, portContentElement); renderResult = markup_1.Markup.renderMarkup(this.getPortLabelMarkup(port.label)); var portLabelElement = renderResult.elem; var portLabelSelectors = renderResult.selectors; if (portLabelElement == null) { throw new Error('Invalid port label markup.'); } var portSelectors; if (portContentSelectors && portLabelSelectors) { // eslint-disable-next-line for (var key in portLabelSelectors) { if (portContentSelectors[key] && key !== this.rootSelector) { throw new Error('Selectors within port must be unique.'); } } portSelectors = __assign(__assign({}, portContentSelectors), portLabelSelectors); } else { portSelectors = portContentSelectors || portLabelSelectors; } util_1.Dom.addClass(portElement, 'x6-port'); util_1.Dom.addClass(portContentElement, 'x6-port-body'); util_1.Dom.addClass(portLabelElement, 'x6-port-label'); portElement.appendChild(portContentElement); portElement.appendChild(portLabelElement); this.portsCache[port.id] = { portElement: portElement, portSelectors: portSelectors, portLabelElement: portLabelElement, portLabelSelectors: portLabelSelectors, portContentElement: portContentElement, portContentSelectors: portContentSelectors, }; this.graph.hook.onPortRendered({ port: port, node: this.cell, container: portElement, selectors: portSelectors, labelContainer: portLabelElement, labelSelectors: portLabelSelectors, contentContainer: portContentElement, contentSelectors: portContentSelectors, }); return portElement; }; NodeView.prototype.updatePorts = function () { var _this = this; // Layout ports without group this.updatePortGroup(); // Layout ports with explicit group var groups = this.cell.getParsedGroups(); Object.keys(groups).forEach(function (groupName) { return _this.updatePortGroup(groupName); }); }; NodeView.prototype.updatePortGroup = function (groupName) { var bbox = geometry_1.Rectangle.fromSize(this.cell.getSize()); var metrics = this.cell.getPortsLayoutByGroup(groupName, bbox); for (var i = 0, n = metrics.length; i < n; i += 1) { var metric = metrics[i]; var portId = metric.portId; var cached = this.portsCache[portId] || {}; var portLayout = metric.portLayout; this.applyPortTransform(cached.portElement, portLayout); if (metric.portAttrs != null) { var options = { selectors: cached.portSelectors || {}, }; if (metric.portSize) { options.rootBBox = geometry_1.Rectangle.fromSize(metric.portSize); } this.updateAttrs(cached.portElement, metric.portAttrs, options); } var labelLayout = metric.labelLayout; if (labelLayout) { this.applyPortTransform(cached.portLabelElement, labelLayout, -(portLayout.angle || 0)); if (labelLayout.attrs) { var options = { selectors: cached.portLabelSelectors || {}, }; if (metric.labelSize) { options.rootBBox = geometry_1.Rectangle.fromSize(metric.labelSize); } this.updateAttrs(cached.portLabelElement, labelLayout.attrs, options); } } } }; NodeView.prototype.applyPortTransform = function (element, layout, initialAngle) { if (initialAngle === void 0) { initialAngle = 0; } var angle = layout.angle; var position = layout.position; var matrix = util_1.Dom.createSVGMatrix() .rotate(initialAngle) .translate(position.x || 0, position.y || 0) .rotate(angle || 0); util_1.Dom.transform(element, matrix, { absolute: true }); }; NodeView.prototype.getPortContainerMarkup = function () { return this.cell.getPortContainerMarkup() || this.defaultPortContainerMarkup; }; NodeView.prototype.getPortMarkup = function (port) { return port.markup || this.cell.portMarkup || this.defaultPortMarkup; }; NodeView.prototype.getPortLabelMarkup = function (label) { return (label.markup || this.cell.portLabelMarkup || this.defaultPortLabelMarkup); }; NodeView.prototype.getEventArgs = function (e, x, y) { var view = this; // eslint-disable-line var node = view.cell; var cell = node; if (x == null || y == null) { return { e: e, view: view, node: node, cell: cell }; } return { e: e, x: x, y: y, view: view, node: node, cell: cell }; }; NodeView.prototype.notifyMouseDown = function (e, x, y) { _super.prototype.onMouseDown.call(this, e, x, y); this.notify('node:mousedown', this.getEventArgs(e, x, y)); }; NodeView.prototype.notifyMouseMove = function (e, x, y) { _super.prototype.onMouseMove.call(this, e, x, y); this.notify('node:mousemove', this.getEventArgs(e, x, y)); }; NodeView.prototype.notifyMouseUp = function (e, x, y) { _super.prototype.onMouseUp.call(this, e, x, y); this.notify('node:mouseup', this.getEventArgs(e, x, y)); }; NodeView.prototype.onClick = function (e, x, y) { _super.prototype.onClick.call(this, e, x, y); this.notify('node:click', this.getEventArgs(e, x, y)); }; NodeView.prototype.onDblClick = function (e, x, y) { _super.prototype.onDblClick.call(this, e, x, y); this.notify('node:dblclick', this.getEventArgs(e, x, y)); }; NodeView.prototype.onContextMenu = function (e, x, y) { _super.prototype.onContextMenu.call(this, e, x, y); this.notify('node:contextmenu', this.getEventArgs(e, x, y)); }; NodeView.prototype.onMouseDown = function (e, x, y) { if (this.isPropagationStopped(e)) { return; } this.notifyMouseDown(e, x, y); this.startNodeDragging(e, x, y); }; NodeView.prototype.onMouseMove = function (e, x, y) { var data = this.getEventData(e); var action = data.action; if (action === 'magnet') { this.dragMagnet(e, x, y); } else { if (action === 'move') { var meta = data; var view = meta.targetView || this; view.dragNode(e, x, y); view.notify('node:moving', { e: e, x: x, y: y, view: view, cell: view.cell, node: view.cell, }); } this.notifyMouseMove(e, x, y); } this.setEventData(e, data); }; NodeView.prototype.onMouseUp = function (e, x, y) { var data = this.getEventData(e); var action = data.action; if (action === 'magnet') { this.stopMagnetDragging(e, x, y); } else { this.notifyMouseUp(e, x, y); if (action === 'move') { var meta = data; var view = meta.targetView || this; view.stopNodeDragging(e, x, y); } } var magnet = data.targetMagnet; if (magnet) { this.onMagnetClick(e, magnet, x, y); } this.checkMouseleave(e); }; NodeView.prototype.onMouseOver = function (e) { _super.prototype.onMouseOver.call(this, e); this.notify('node:mouseover', this.getEventArgs(e)); }; NodeView.prototype.onMouseOut = function (e) { _super.prototype.onMouseOut.call(this, e); this.notify('node:mouseout', this.getEventArgs(e)); }; NodeView.prototype.onMouseEnter = function (e) { this.updateClassName(e); _super.prototype.onMouseEnter.call(this, e); this.notify('node:mouseenter', this.getEventArgs(e)); }; NodeView.prototype.onMouseLeave = function (e) { _super.prototype.onMouseLeave.call(this, e); this.notify('node:mouseleave', this.getEventArgs(e)); }; NodeView.prototype.onMouseWheel = function (e, x, y, delta) { _super.prototype.onMouseWheel.call(this, e, x, y, delta); this.notify('node:mousewheel', __assign({ delta: delta }, this.getEventArgs(e, x, y))); }; NodeView.prototype.onMagnetClick = function (e, magnet, x, y) { var count = this.graph.view.getMouseMovedCount(e); if (count > this.graph.options.clickThreshold) { return; } this.notify('node:magnet:click', __assign({ magnet: magnet }, this.getEventArgs(e, x, y))); }; NodeView.prototype.onMagnetDblClick = function (e, magnet, x, y) { this.notify('node:magnet:dblclick', __assign({ magnet: magnet }, this.getEventArgs(e, x, y))); }; NodeView.prototype.onMagnetContextMenu = function (e, magnet, x, y) { this.notify('node:magnet:contextmenu', __assign({ magnet: magnet }, this.getEventArgs(e, x, y))); }; NodeView.prototype.onMagnetMouseDown = function (e, magnet, x, y) { this.startMagnetDragging(e, x, y); }; NodeView.prototype.onCustomEvent = function (e, name, x, y) { this.notify('node:customevent', __assign({ name: name }, this.getEventArgs(e, x, y))); _super.prototype.onCustomEvent.call(this, e, name, x, y); }; NodeView.prototype.prepareEmbedding = function (e) { // const cell = data.cell || this.cell // const graph = data.graph || this.graph // const model = graph.model // model.startBatch('to-front') // // Bring the model to the front with all his embeds. // cell.toFront({ deep: true, ui: true }) // const maxZ = model // .getNodes() // .reduce((max, cell) => Math.max(max, cell.getZIndex() || 0), 0) // const connectedEdges = model.getConnectedEdges(cell, { // deep: true, // enclosed: true, // }) // connectedEdges.forEach((edge) => { // const zIndex = edge.getZIndex() || 0 // if (zIndex <= maxZ) { // edge.setZIndex(maxZ + 1, { ui: true }) // } // }) // model.stopBatch('to-front') // Before we start looking for suitable parent we remove the current one. // const parent = cell.getParent() // if (parent) { // parent.unembed(cell, { ui: true }) // } var data = this.getEventData(e); var node = data.cell || this.cell; var view = this.graph.findViewByCell(node); var localPoint = this.graph.snapToGrid(e.clientX, e.clientY); this.notify('node:embed', { e: e, node: node, view: view, cell: node, x: localPoint.x, y: localPoint.y, currentParent: node.getParent(), }); }; NodeView.prototype.processEmbedding = function (e, data) { var _this = this; var cell = data.cell || this.cell; var graph = data.graph || this.graph; var options = graph.options.embedding; var findParent = options.findParent; var candidates = typeof findParent === 'function' ? util_1.FunctionExt.call(findParent, graph, { view: this, node: this.cell, }).filter(function (c) { return (cell_1.Cell.isCell(c) && _this.cell.id !== c.id && !c.isDescendantOf(_this.cell)); }) : graph.model.getNodesUnderNode(cell, { by: findParent, }); // Picks the node with the highest `z` index if (options.frontOnly) { candidates = candidates.slice(-1); } var newCandidateView = null; var prevCandidateView = data.candidateEmbedView; var validateEmbeding = options.validate; for (var i = candidates.length - 1; i >= 0; i -= 1) { var candidate = candidates[i]; if (prevCandidateView && prevCandidateView.cell.id === candidate.id) { // candidate remains the same newCandidateView = prevCandidateView; break; } else { var view = candidate.findView(graph); if (util_1.FunctionExt.call(validateEmbeding, graph, { child: this.cell, parent: view.cell, childView: this, parentView: view, })) { // flip to the new candidate newCandidateView = view; break; } } } this.clearEmbedding(data); if (newCandidateView) { newCandidateView.highlight(null, { type: 'embedding' }); } data.candidateEmbedView = newCandidateView; var localPoint = graph.snapToGrid(e.clientX, e.clientY); this.notify('node:embedding', { e: e, cell: cell, node: cell, view: graph.findViewByCell(cell), x: localPoint.x, y: localPoint.y, currentParent: cell.getParent(), candidateParent: newCandidateView ? newCandidateView.cell : null, }); }; NodeView.prototype.clearEmbedding = function (data) { var candidateView = data.candidateEmbedView; if (candidateView) { candidateView.unhighlight(null, { type: 'embedding' }); data.candidateEmbedView = null; } }; NodeView.prototype.finalizeEmbedding = function (e, data) { var cell = data.cell || this.cell; var graph = data.graph || this.graph; var view = graph.findViewByCell(cell); var parent = cell.getParent(); var candidateView = data.candidateEmbedView; if (candidateView) { // Candidate view is chosen to become the parent of the node. candidateView.unhighlight(null, { type: 'embedding' }); data.candidateEmbedView = null; if (parent == null || parent.id !== candidateView.cell.id) { candidateView.cell.insertChild(cell, undefined, { ui: true }); } } else if (parent) { parent.unembed(cell, { ui: true }); } graph.model.getConnectedEdges(cell, { deep: true }).forEach(function (edge) { edge.updateParent({ ui: true }); }); var localPoint = graph.snapToGrid(e.clientX, e.clientY); if (view) { view.notify('node:embedded', { e: e, cell: cell, x: localPoint.x, y: localPoint.y, node: cell, view: graph.findViewByCell(cell), previousParent: parent, currentParent: cell.getParent(), }); } }; NodeView.prototype.getDelegatedView = function () { var cell = this.cell; var view = this; // eslint-disable-line while (view) { if (cell.isEdge()) { break; } if (!cell.hasParent() || view.can('stopDelegateOnDragging')) { return view; } cell = cell.getParent(); view = this.graph.renderer.findViewByCell(cell); } return null; }; NodeView.prototype.startMagnetDragging = function (e, x, y) { if (!this.can('magnetConnectable')) { return; } e.stopPropagation(); var magnet = e.currentTarget; var graph = this.graph; this.setEventData(e, { targetMagnet: magnet, }); if (graph.hook.validateMagnet(this, magnet, e)) { if (graph.options.magnetThreshold <= 0) { this.startConnectting(e, magnet, x, y); } this.setEventData(e, { action: 'magnet', }); this.stopPropagation(e); } else { this.onMouseDown(e, x, y); } graph.view.delegateDragEvents(e, this); }; NodeView.prototype.startConnectting = function (e, magnet, x, y) { this.graph.model.startBatch('add-edge'); var edgeView = this.createEdgeFromMagnet(magnet, x, y); edgeView.notifyMouseDown(e, x, y); // backwards compatibility events edgeView.setEventData(e, edgeView.prepareArrowheadDragging('target', { x: x, y: y, isNewEdge: true, fallbackAction: 'remove', })); this.setEventData(e, { edgeView: edgeView }); }; NodeView.prototype.createEdgeFromMagnet = function (magnet, x, y) { var graph = this.graph; var model = graph.model; var edge = graph.hook.getDefaultEdge(this, magnet); edge.setSource(__assign(__assign({}, edge.getSource()), this.getEdgeTerminal(magnet, x, y, edge, 'source'))); edge.setTarget(__assign(__assign({}, edge.getTarget()), { x: x, y: y })); edge.addTo(model, { async: false, ui: true }); return edge.findView(graph); }; NodeView.prototype.dragMagnet = function (e, x, y) { var data = this.getEventData(e); var edgeView = data.edgeView; if (edgeView) { edgeView.onMouseMove(e, x, y); this.autoScrollGraph(e.clientX, e.clientY); } else { var graph = this.graph; var magnetThreshold = graph.options.magnetThreshold; var currentTarget = this.getEventTarget(e); var targetMagnet = data.targetMagnet; // magnetThreshold when the pointer leaves the magnet if (magnetThreshold === 'onleave') { if (targetMagnet === currentTarget || targetMagnet.contains(currentTarget)) { return; } // eslint-disable-next-line no-lonely-if } else { // magnetThreshold defined as a number of movements if (graph.view.getMouseMovedCount(e) <= magnetThreshold) { return; } } this.startConnectting(e, targetMagnet, x, y); } }; NodeView.prototype.stopMagnetDragging = function (e, x, y) { var data = this.eventData(e); var edgeView = data.edgeView; if (edgeView) { edgeView.onMouseUp(e, x, y); this.graph.model.stopBatch('add-edge'); } }; NodeView.prototype.notifyUnhandledMouseDown = function (e, x, y) { this.notify('node:unhandled:mousedown', { e: e, x: x, y: y, view: this, cell: this.cell, node: this.cell, }); }; NodeView.prototype.notifyNodeMove = function (name, e, x, y, cell) { var _this = this; var cells = [cell]; var selection = this.graph.selection.widget; if (selection && selection.options.movable) { var selectedCells = this.graph.getSelectedCells(); if (selectedCells.includes(cell)) { cells = selectedCells.filter(function (c) { return c.isNode(); }); } } cells.forEach(function (c) { _this.notify(name, { e: e, x: x, y: y, cell: c, node: c, view: c.findView(_this.graph), }); }); }; NodeView.prototype.startNodeDragging = function (e, x, y) { var targetView = this.getDelegatedView(); if (targetView == null || !targetView.can('nodeMovable')) { return this.notifyUnhandledMouseDown(e, x, y); } this.setEventData(e, { targetView: targetView, action: 'move', }); var position = geometry_1.Point.create(targetView.cell.getPosition()); targetView.setEventData(e, { moving: false, offset: position.diff(x, y), restrict: this.graph.hook.getRestrictArea(targetView), }); }; NodeView.prototype.dragNode = function (e, x, y) { var node = this.cell; var graph = this.graph; var gridSize = graph.getGridSize(); var data = this.getEventData(e); var offset = data.offset; var restrict = data.restrict; if (!data.moving) { data.moving = true; this.addClass('node-moving'); this.notifyNodeMove('node:move', e, x, y, this.cell); } this.autoScrollGraph(e.clientX, e.clientY); var posX = global_1.Util.snapToGrid(x + offset.x, gridSize); var posY = global_1.Util.snapToGrid(y + offset.y, gridSize); node.setPosition(posX, posY, { restrict: restrict, deep: true, ui: true, }); if (graph.options.embedding.enabled) { if (!data.embedding) { this.prepareEmbedding(e); data.embedding = true; } this.processEmbedding(e, data); } }; NodeView.prototype.stopNodeDragging = function (e, x, y) { var data = this.getEventData(e); if (data.embedding) { this.finalizeEmbedding(e, data); } if (data.moving) { this.removeClass('node-moving'); this.notifyNodeMove('node:moved', e, x, y, this.cell); } data.moving = false; data.embedding = false; }; NodeView.prototype.autoScrollGraph = function (x, y) { var scroller = this.graph.scroller.widget; if (scroller) { scroller.autoScroll(x, y); } }; return NodeView; }(cell_2.CellView)); exports.NodeView = NodeView; (function (NodeView) { NodeView.toStringTag = "X6." + NodeView.name; function isNodeView(instance) { if (instance == null) { return false; } if (instance instanceof NodeView) { return true; } var tag = instance[Symbol.toStringTag]; var view = instance; if ((tag == null || tag === NodeView.toStringTag) && typeof view.isNodeView === 'function' && typeof view.isEdgeView === 'function' && typeof view.confirmUpdate === 'function' && typeof view.update === 'function' && typeof view.findPortElem === 'function' && typeof view.resize === 'function' && typeof view.rotate === 'function' && typeof view.translate === 'function') { return true; } return false; } NodeView.isNodeView = isNodeView; })(NodeView = exports.NodeView || (exports.NodeView = {})); exports.NodeView = NodeView; NodeView.config({ isSvgElement: true, priority: 0, bootstrap: ['render'], actions: { view: ['render'], markup: ['render'], attrs: ['update'], size: ['resize', 'ports', 'tools'], angle: ['rotate', 'tools'], position: ['translate', 'tools'], ports: ['ports'], tools: ['tools'], }, }); NodeView.registry.register('node', NodeView, true); //# sourceMappingURL=node.js.map