@kieler/klighd-core
Version:
Core KLighD diagram visualization with Sprotty
172 lines • 7.93 kB
JavaScript
;
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