UNPKG

@kieler/klighd-core

Version:

Core KLighD diagram visualization with Sprotty

172 lines 7.93 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getElementByID = exports.findRendering = exports.hasAction = exports.getSemanticElement = void 0; const proxy_view_util_1 = require("./proxy-view/proxy-view-util"); const skgraph_models_1 = require("./skgraph-models"); /* global Element, SVGElement */ /** * Returns the SVG element in the DOM that represents the topmost KRendering in the hierarchy. * If an action should be triggered on the element, bubble up through the rendering hierarchy until the first actionable rendering.. * @param target The graph element the event is triggered on. * @param element The topmost SVG element clicked. * @param actionable Optional parameter to search for actionable renderings only. Defaults to false. */ function getSemanticElement(target, element, actionable = false) { if (!(element instanceof SVGElement)) { return undefined; } let currentElement = element; let semanticElement; while (semanticElement === undefined && currentElement instanceof SVGElement) { // Check if the rendering has an action. let renderingHasAction = true; if (currentElement.id !== '' && actionable) { const rendering = findRendering(target, currentElement); if (!rendering) { // If no rendering for this ID exists, we have gone too far up to the next graph element. Skip from here. return undefined; } if (!hasAction(rendering)) { renderingHasAction = false; } } // Choose this element if it is a defined element with an ID. // Also only use this if there is an action and we look for an actionable rendering (action => renderingHasAction) if (currentElement.id !== '' && (!actionable || renderingHasAction)) { semanticElement = currentElement; } else { currentElement = currentElement.parentElement; } } return semanticElement; } exports.getSemanticElement = getSemanticElement; /** * Returns if there is a KLighD action defined on the given rendering that needs to be handled. * * @param rendering the rendering that may define an action to be executed. * @param includeChildren if this should also search for actions in any of the rendering's children. * Defaults to false. * @returns if there is at least one action for this rendering. */ function hasAction(rendering, includeChildren = false) { if (rendering.actions && rendering.actions.length !== 0) { return true; } if (includeChildren && (0, skgraph_models_1.isContainerRendering)(rendering)) { for (const child of rendering.children) { if (hasAction(child, includeChildren)) { return true; } } if ((0, skgraph_models_1.isPolyline)(rendering)) { if (hasAction(rendering.junctionPointRendering, includeChildren)) { return true; } } } return false; } exports.hasAction = hasAction; /** * Finds the KRendering in the data of the SKGraphElement that matches the given ID. * @param graphElement The graph element to look in. * @param svgElement The SVG element that represents the rendering. */ function findRendering(graphElement, svgElement) { var _a; const isProxy = (0, proxy_view_util_1.isProxyRendering)(svgElement, graphElement.id); const svgId = svgElement.id; // The first rendering has to be extracted from the SKGraphElement. It is the first data object that is a KRendering. let data; if (isProxy) { // For a proxy, the rendering may be in the graph element's properties. data = graphElement.properties['de.cau.cs.kieler.klighd.proxyView.proxyRendering']; } if (data === undefined) { // Non-proxies and proxies without an explicit proxy rendering just use the graph element's data. data = graphElement.data; } let currentElement = data.find((possibleRendering) => (0, skgraph_models_1.isRendering)(possibleRendering)); // The real rendering ID starts after the graph element ID prefix, delimited by a $$$. const renderingId = (_a = svgId.split('$$$')[1]) !== null && _a !== void 0 ? _a : svgId; if (renderingId === undefined) { return undefined; } const idPath = renderingId.split('$'); if (currentElement.type === skgraph_models_1.K_RENDERING_REF) { // KRenderingRefs' ids always start with the identifying name of the reference and may continue with $<something> to refer to renderings within that reference. // Start with index 1 since the currentElement already contains the rendering with the identifying name. // for (let i = 1; i < idPath.length; i++) { // TODO:looking up renderings in rendering references is not supported yet. return undefined; } // The rendering id is build hierarchically and the first rendering is already found, so start with index 1 as a $ sign can be skipped. for (let i = 1; i < idPath.length; i++) { let nextElement; if ((0, skgraph_models_1.isContainerRendering)(currentElement)) { // First, look for the ID in the child renderings. nextElement = currentElement.children.find((childRendering) => svgId.startsWith(childRendering.properties['klighd.lsp.rendering.id'])); } if (nextElement === undefined && currentElement.type === skgraph_models_1.K_POLYLINE) { // If the rendering was not found yet, take the junction point rendering. if (svgId.startsWith(currentElement.junctionPointRendering.properties['klighd.lsp.rendering.id'])) { nextElement = currentElement.junctionPointRendering; } } if (nextElement === undefined) { // This ID does not exist in the renderings, therefore does not belong to them. return undefined; } currentElement = nextElement; } // Now the currentElement should be the element searched for by the id. if (currentElement.properties['klighd.lsp.rendering.id'] !== svgId) { console.error(`The found element does not match the searched id! id: ${svgId}, found element: ${currentElement}`); return undefined; } return currentElement; } exports.findRendering = findRendering; /** * Finds the SKGraphElement that matches the given ID. * @param root The root. * @param id The ID to search for. * @returns The element matching the given id or `undefined` if there is none. */ function getElementByID(root, id, suppressErrors = false) { let curr = root; const idPath = id.split('$'); // The node id is build hierarchically and the root is already given, so start with i=1 ($root) for (let i = 1; i < idPath.length && curr; i++) { // $$ in id (e.g. comments in sccharts) if (idPath[i].length > 0) { const nextType = idPath[i].charAt(0); if (nextType === 'E') { // Edge curr = curr.outgoingEdges.find((edge) => id.startsWith(edge.id)); } else if (['N', 'L', 'P'].includes(nextType) || idPath[i] === 'root') { // Node, label or port curr = curr.children.find((node) => id.startsWith(node.id)); } } } // Now currNode should be the node searched for by the id if (!curr) { if (!suppressErrors) { console.error('No node found matching the id:', id); } return undefined; } if (curr.id !== id) { if (!suppressErrors) { console.error('The found node does not match the searched id! id:', id, ', found node:', curr); } return undefined; } return curr; } exports.getElementByID = getElementByID; //# sourceMappingURL=skgraph-utils.js.map