@kieler/klighd-core
Version:
Core KLighD diagram visualization with Sprotty
408 lines • 19.9 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.KEdgeView = exports.KLabelView = exports.KPortView = exports.KNodeView = exports.SKGraphView = void 0;
/*
* KIELER - Kiel Integrated Environment for Layout Eclipse RichClient
*
* http://rtsys.informatik.uni-kiel.de/kieler
*
* Copyright 2019-2023 by
* + Kiel University
* + Department of Computer Science
* + Real-Time and Embedded Systems Group
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*/
/** @jsx svg */
const helper_methods_1 = require("@kieler/klighd-interactive/lib/helper-methods");
const interactive_view_1 = require("@kieler/klighd-interactive/lib/interactive-view");
const klighd_interactive_mouselistener_1 = require("@kieler/klighd-interactive/lib/klighd-interactive-mouselistener");
const layered_relative_constraint_view_1 = require("@kieler/klighd-interactive/lib/layered/layered-relative-constraint-view");
const inversify_1 = require("inversify");
const sprotty_1 = require("sprotty");
const actions_1 = require("./actions/actions");
const depth_map_1 = require("./depth-map");
const di_symbols_1 = require("./di.symbols");
const overpass_1 = require("./fonts/overpass");
const render_options_registry_1 = require("./options/render-options-registry");
const skgraph_models_1 = require("./skgraph-models");
const views_rendering_1 = require("./views-rendering");
const views_styles_1 = require("./views-styles");
/**
* IView component that turns an SGraph element and its children into a tree of virtual DOM elements.
* Extends the SGraphView by initializing the context for KGraph rendering.
*/
let SKGraphView = class SKGraphView {
render(model, context) {
const ctx = context;
this.actionDispatcher.dispatch(actions_1.SendModelContextAction.create(model, ctx));
if (!ctx.renderingDefs) {
// Make sure not to create a new map all the time
ctx.renderingDefs = new Map();
}
ctx.renderingDefs.set('font', fontDefinition());
ctx.mListener = this.mListener;
ctx.renderOptionsRegistry = this.renderOptionsRegistry;
const viewport = (0, sprotty_1.findParentByFeature)(model, sprotty_1.isViewport);
if (viewport) {
ctx.viewport = viewport;
}
ctx.titleStorage.clear();
// Add depthMap to context for rendering, when required.
const smartZoomOption = ctx.renderOptionsRegistry.getValue(render_options_registry_1.UseSmartZoom);
// Only enable, if option is found.
const useSmartZoom = smartZoomOption !== null && smartZoomOption !== void 0 ? smartZoomOption : false;
if (useSmartZoom && ctx.targetKind !== 'hidden') {
ctx.depthMap = depth_map_1.DepthMap.getDM();
if (!ctx.forceRendering && ctx.viewport && ctx.depthMap) {
ctx.depthMap.updateDetailLevels(ctx.viewport, ctx.renderOptionsRegistry);
}
}
else {
ctx.depthMap = undefined;
}
const transform = `scale(${model.zoom}) translate(${-model.scroll.x},${-model.scroll.y})`;
return ((0, sprotty_1.svg)("svg", { "class-sprotty-graph": true },
(0, sprotty_1.svg)("g", { transform: transform }, context.renderChildren(model))));
}
};
exports.SKGraphView = SKGraphView;
__decorate([
(0, inversify_1.inject)(klighd_interactive_mouselistener_1.KlighdInteractiveMouseListener),
__metadata("design:type", klighd_interactive_mouselistener_1.KlighdInteractiveMouseListener)
], SKGraphView.prototype, "mListener", void 0);
__decorate([
(0, inversify_1.inject)(di_symbols_1.DISymbol.RenderOptionsRegistry),
__metadata("design:type", render_options_registry_1.RenderOptionsRegistry)
], SKGraphView.prototype, "renderOptionsRegistry", void 0);
__decorate([
(0, inversify_1.inject)(sprotty_1.TYPES.IActionDispatcher),
__metadata("design:type", Object)
], SKGraphView.prototype, "actionDispatcher", void 0);
exports.SKGraphView = SKGraphView = __decorate([
(0, inversify_1.injectable)()
], SKGraphView);
/**
* IView component that translates a KNode and its children into a tree of virtual DOM elements.
*/
let KNodeView = class KNodeView {
render(node, context) {
// Add new level to title and position array for correct placement of titles
const ctx = context;
if (!ctx.forceRendering && ctx.depthMap) {
const containingRegion = ctx.depthMap.getContainingRegion(node, ctx.viewport, ctx.renderOptionsRegistry);
if (ctx.depthMap && containingRegion && containingRegion.detail !== depth_map_1.DetailLevel.FullDetails) {
// Make sure this node and its children are not drawn as long as it is not on full details.
node.areChildAreaChildrenRendered = true;
node.areNonChildAreaChildrenRendered = true;
return undefined;
}
}
// reset these properties, if the diagram is drawn a second time
node.areChildAreaChildrenRendered = false;
node.areNonChildAreaChildrenRendered = false;
const result = [];
const isShadow = node.shadow;
let shadow;
let interactiveNodes;
let interactiveConstraints;
if (isShadow) {
// Render shadow of the node
shadow = (0, views_rendering_1.getRendering)(node.data, node, new views_styles_1.KStyles(false), ctx);
if (this.mListener.relativeConstraintMode) {
// render visualization for relative constraints
result.push((0, layered_relative_constraint_view_1.renderRelativeConstraint)(node.parent, node));
}
}
if ((0, helper_methods_1.isChildSelected)(node)) {
if (node.properties['org.eclipse.elk.interactiveLayout'] && ctx.mListener.hasDragged) {
// Render the visualization for interactive layout
interactiveNodes = (0, interactive_view_1.renderInteractiveLayout)(node, this.mListener.relativeConstraintMode);
}
}
// Render nodes and constraint icon. All nodes that are not moved do not have a shadow and have their opacity set to 0.1.
node.shadow = false;
let rendering;
if (!ctx.mListener.hasDragged || (0, helper_methods_1.isChildSelected)(node.parent)) {
if (node.forbidden) {
node.opacity = 0.1;
}
// Node should only be visible if the node is in the same hierarchical level as the moved node or no node is moved at all
rendering = (0, views_rendering_1.getRendering)(node.data, node, new views_styles_1.KStyles(false), ctx);
if (ctx.renderOptionsRegistry.getValue(render_options_registry_1.ShowConstraintOption) &&
node.parent.properties &&
node.parent.properties['org.eclipse.elk.interactiveLayout']) {
// render icon visualizing the set Constraints
interactiveConstraints = (0, interactive_view_1.renderConstraints)(node);
}
// Currently does not work, since it changes the order of teh nodes in the dom.
// After setting a constraint and deleting it afterwards this leads to the problem that one node is there twice and one is gone
// until the diagram is again updated.
// if (node.selected) {
// let root = node.parent
// while ((root as SKNode).parent) {
// root = (root as SKNode).parent
// }
// new BringToFrontCommand(new BringToFrontAction([node.id])).execute({
// root: root as SModelRoot,
// modelFactory: this.graphFactory,
// duration: 100,
// modelChanged: undefined!,
// logger: new ConsoleLogger(),
// syncer: new AnimationFrameSyncer()
// })
// }
}
else {
node.opacity = 0.1;
rendering = (0, views_rendering_1.getRendering)(node.data, node, new views_styles_1.KStyles(false), ctx);
}
node.shadow = isShadow;
node.highlight = false;
if (node.id === '$root') {
// The root node should not be rendered, only its children should.
const children = ctx.renderChildren(node);
// Add all color and shadow definitions put into the context by the child renderings.
const defs = (0, sprotty_1.svg)("defs", null);
ctx.renderingDefs.forEach((value) => {
;
defs.children.push(value);
});
result.push(defs);
if (interactiveNodes) {
result.push(interactiveNodes);
}
result.push(...children);
const title = ctx.titleStorage.getTitle();
if (title !== undefined) {
result.push(title);
}
return (0, sprotty_1.svg)("g", null, ...result);
}
// Add renderings that are not undefined
if (shadow !== undefined) {
result.push(shadow);
}
if (rendering !== undefined) {
result.push(rendering);
}
else {
const title = ctx.titleStorage.getTitle();
if (title !== undefined) {
result.push(title);
}
return ((0, sprotty_1.svg)("g", null, title !== null && title !== void 0 ? title : [],
ctx.renderChildren(node)));
}
if (interactiveNodes) {
result.push(interactiveNodes);
}
if (interactiveConstraints) {
result.push(interactiveConstraints);
}
// Default case. If no child area children or no non-child area children are already rendered within the rendering, add the children by default.
if (!node.areChildAreaChildrenRendered) {
result.push(...ctx.renderChildren(node));
}
else if (!node.areNonChildAreaChildrenRendered) {
result.push(...ctx.renderNonChildAreaChildren(node));
}
const title = ctx.titleStorage.getTitle();
if (title !== undefined) {
result.push(title);
}
return (0, sprotty_1.svg)("g", null, ...result);
}
};
exports.KNodeView = KNodeView;
__decorate([
(0, inversify_1.inject)(klighd_interactive_mouselistener_1.KlighdInteractiveMouseListener),
__metadata("design:type", klighd_interactive_mouselistener_1.KlighdInteractiveMouseListener)
], KNodeView.prototype, "mListener", void 0);
exports.KNodeView = KNodeView = __decorate([
(0, inversify_1.injectable)()
], KNodeView);
/**
* IView component that translates a KPort and its children into a tree of virtual DOM elements.
*/
let KPortView = class KPortView {
render(port, context) {
var _a, _b, _c, _d;
// Add new level to title and position array for correct placement of titles
const ctx = context;
if (!ctx.forceRendering && ctx.depthMap) {
const containingRegion = ctx.depthMap.getContainingRegion(port, ctx.viewport, ctx.renderOptionsRegistry);
if (ctx.depthMap && containingRegion && containingRegion.detail !== depth_map_1.DetailLevel.FullDetails) {
port.areChildAreaChildrenRendered = true;
port.areNonChildAreaChildrenRendered = true;
return undefined;
}
}
port.areChildAreaChildrenRendered = false;
port.areNonChildAreaChildrenRendered = false;
const rendering = (0, views_rendering_1.getRendering)(port.data, port, new views_styles_1.KStyles(false), ctx);
// If no rendering could be found, just render its children.
if (rendering === undefined) {
const element = ((0, sprotty_1.svg)("g", null, (_a = ctx.titleStorage.getTitle()) !== null && _a !== void 0 ? _a : [],
ctx.renderChildren(port)));
return element;
}
// Default case. If no child area children or no non-child area children are already rendered within the rendering, add the children by default.
let element;
if (!port.areChildAreaChildrenRendered) {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_b = ctx.titleStorage.getTitle()) !== null && _b !== void 0 ? _b : [],
ctx.renderChildren(port)));
}
else if (!port.areNonChildAreaChildrenRendered) {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_c = ctx.titleStorage.getTitle()) !== null && _c !== void 0 ? _c : [],
ctx.renderNonChildAreaChildren(port)));
}
else {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_d = ctx.titleStorage.getTitle()) !== null && _d !== void 0 ? _d : []));
}
return element;
}
};
exports.KPortView = KPortView;
exports.KPortView = KPortView = __decorate([
(0, inversify_1.injectable)()
], KPortView);
/**
* IView component that translates a KLabel and its children into a tree of virtual DOM elements.
*/
let KLabelView = class KLabelView {
render(label, context) {
var _a, _b, _c, _d;
// Add new level to title and position array for correct placement of titles
const ctx = context;
if (!ctx.forceRendering && ctx.depthMap) {
const containingRegion = ctx.depthMap.getContainingRegion(label, ctx.viewport, ctx.renderOptionsRegistry);
if (ctx.depthMap && containingRegion && containingRegion.detail !== depth_map_1.DetailLevel.FullDetails) {
label.areChildAreaChildrenRendered = true;
label.areNonChildAreaChildrenRendered = true;
return undefined;
}
}
label.areChildAreaChildrenRendered = false;
label.areNonChildAreaChildrenRendered = false;
// let parent = label.parent
if (ctx.mListener.hasDragged) {
// Nodes that are not on the same hierarchy are less visible.
label.opacity = 0.1;
}
const rendering = (0, views_rendering_1.getRendering)(label.data, label, new views_styles_1.KStyles(false), ctx);
// If no rendering could be found, just render its children.
if (rendering === undefined) {
const element = ((0, sprotty_1.svg)("g", null, (_a = ctx.titleStorage.getTitle()) !== null && _a !== void 0 ? _a : [],
ctx.renderChildren(label)));
return element;
}
// Default case. If no child area children or no non-child area children are already rendered within the rendering, add the children by default.
let element;
if (!label.areChildAreaChildrenRendered) {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_b = ctx.titleStorage.getTitle()) !== null && _b !== void 0 ? _b : [],
ctx.renderChildren(label)));
}
else if (!label.areNonChildAreaChildrenRendered) {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_c = ctx.titleStorage.getTitle()) !== null && _c !== void 0 ? _c : [],
ctx.renderNonChildAreaChildren(label)));
}
else {
element = ((0, sprotty_1.svg)("g", null,
rendering, (_d = ctx.titleStorage.getTitle()) !== null && _d !== void 0 ? _d : []));
}
return element;
}
};
exports.KLabelView = KLabelView;
exports.KLabelView = KLabelView = __decorate([
(0, inversify_1.injectable)()
], KLabelView);
/**
* IView component that translates a KEdge and its children into a tree of virtual DOM elements.
*/
let KEdgeView = class KEdgeView {
render(edge, context) {
const ctx = context;
if (!ctx.forceRendering && ctx.depthMap) {
const containingRegion = ctx.depthMap.getContainingRegion(edge, ctx.viewport, ctx.renderOptionsRegistry);
if (ctx.depthMap && containingRegion && containingRegion.detail !== depth_map_1.DetailLevel.FullDetails) {
edge.areChildAreaChildrenRendered = true;
edge.areNonChildAreaChildrenRendered = true;
return undefined;
}
}
edge.areChildAreaChildrenRendered = false;
edge.areNonChildAreaChildrenRendered = false;
const s = edge.source;
const t = edge.target;
// Do not draw edges without a source or target.
if (s === undefined || t === undefined) {
return (0, sprotty_1.svg)("g", null);
}
// edge should be greyed out if the source or target is moved
if (s !== undefined && t !== undefined && s instanceof skgraph_models_1.SKNode && t instanceof skgraph_models_1.SKNode) {
edge.moved = (s.selected || t.selected) && ctx.mListener.hasDragged;
}
let rendering;
if (!ctx.mListener.hasDragged || (0, helper_methods_1.isChildSelected)(edge.parent)) {
// edge should only be visible if it is in the same hierarchical level as
// the moved node or no node is moved at all
rendering = (0, views_rendering_1.getRendering)(edge.data, edge, new views_styles_1.KStyles(false), ctx);
}
edge.moved = false;
// Also get the renderings for all junction points
const junctionPointRenderings = (0, views_rendering_1.getJunctionPointRenderings)(edge, ctx);
// If no rendering could be found, just render its children.
if (rendering === undefined) {
return ((0, sprotty_1.svg)("g", null,
ctx.renderChildren(edge),
...junctionPointRenderings));
}
// Default case. If no child area children or no non-child area children are already rendered within the rendering, add the children by default.
if (!edge.areChildAreaChildrenRendered) {
return ((0, sprotty_1.svg)("g", null,
rendering,
ctx.renderChildren(edge),
...junctionPointRenderings));
}
if (!edge.areNonChildAreaChildrenRendered) {
return ((0, sprotty_1.svg)("g", null,
rendering,
ctx.renderNonChildAreaChildren(edge),
...junctionPointRenderings));
}
return ((0, sprotty_1.svg)("g", null,
rendering,
...junctionPointRenderings));
}
};
exports.KEdgeView = KEdgeView;
exports.KEdgeView = KEdgeView = __decorate([
(0, inversify_1.injectable)()
], KEdgeView);
function fontDefinition() {
// TODO: maybe find a way to only include the font if it is used in the SVG.
return ((0, sprotty_1.svg)("style", null,
overpass_1.overpassRegularStyle,
overpass_1.overpassMonoRegularStyle));
}
//# sourceMappingURL=views.js.map