2023-09-05 11:13:27 +02:00
|
|
|
import { getStylesFromArray } from '../../utils.js';
|
2023-09-14 10:11:43 +02:00
|
|
|
import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
|
2023-09-05 11:13:27 +02:00
|
|
|
import { getConfig } from '../../config.js';
|
|
|
|
import { ContainerElement } from 'd3';
|
|
|
|
import type { Block } from './blockTypes.js';
|
|
|
|
import { BlockDB } from './blockDB.js';
|
|
|
|
|
2023-10-15 22:21:25 +02:00
|
|
|
interface Node {
|
|
|
|
classes: string;
|
|
|
|
}
|
|
|
|
|
2023-10-03 12:56:47 +02:00
|
|
|
function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
|
2023-09-05 11:13:27 +02:00
|
|
|
const vertex = block;
|
|
|
|
|
|
|
|
let classStr = 'default';
|
2023-10-15 22:21:25 +02:00
|
|
|
if ((vertex?.classes?.length || 0) > 0) {
|
|
|
|
classStr = (vertex?.classes || []).join(' ');
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
classStr = classStr + ' flowchart-label';
|
|
|
|
|
|
|
|
// We create a SVG label, either by delegating to addHtmlLabel or manually
|
|
|
|
let radious = 0;
|
|
|
|
let _shape = '';
|
|
|
|
let layoutOptions = {};
|
2023-10-20 12:30:25 +02:00
|
|
|
let padding;
|
2023-09-05 11:13:27 +02:00
|
|
|
// Set the shape based parameters
|
|
|
|
switch (vertex.type) {
|
|
|
|
case 'round':
|
|
|
|
radious = 5;
|
|
|
|
_shape = 'rect';
|
|
|
|
break;
|
2023-10-20 12:30:25 +02:00
|
|
|
// case 'composite-subgraph':
|
|
|
|
// radious = 0;
|
|
|
|
// _shape = 'composite';
|
|
|
|
// break;
|
2023-10-03 14:19:08 +02:00
|
|
|
case 'composite':
|
2023-10-20 12:30:25 +02:00
|
|
|
radious = 0;
|
2023-10-03 14:19:08 +02:00
|
|
|
_shape = 'composite';
|
2023-10-20 12:30:25 +02:00
|
|
|
padding = 0;
|
2023-10-03 14:19:08 +02:00
|
|
|
break;
|
2023-09-05 11:13:27 +02:00
|
|
|
case 'square':
|
|
|
|
_shape = 'rect';
|
|
|
|
break;
|
|
|
|
case 'diamond':
|
|
|
|
_shape = 'question';
|
|
|
|
layoutOptions = {
|
|
|
|
portConstraints: 'FIXED_SIDE',
|
|
|
|
};
|
|
|
|
break;
|
|
|
|
case 'hexagon':
|
|
|
|
_shape = 'hexagon';
|
|
|
|
break;
|
|
|
|
case 'odd':
|
|
|
|
_shape = 'rect_left_inv_arrow';
|
|
|
|
break;
|
|
|
|
case 'lean_right':
|
|
|
|
_shape = 'lean_right';
|
|
|
|
break;
|
|
|
|
case 'lean_left':
|
|
|
|
_shape = 'lean_left';
|
|
|
|
break;
|
|
|
|
case 'trapezoid':
|
|
|
|
_shape = 'trapezoid';
|
|
|
|
break;
|
|
|
|
case 'inv_trapezoid':
|
|
|
|
_shape = 'inv_trapezoid';
|
|
|
|
break;
|
|
|
|
case 'odd_right':
|
|
|
|
_shape = 'rect_left_inv_arrow';
|
|
|
|
break;
|
|
|
|
case 'circle':
|
|
|
|
_shape = 'circle';
|
|
|
|
break;
|
|
|
|
case 'ellipse':
|
|
|
|
_shape = 'ellipse';
|
|
|
|
break;
|
|
|
|
case 'stadium':
|
|
|
|
_shape = 'stadium';
|
|
|
|
break;
|
|
|
|
case 'subroutine':
|
|
|
|
_shape = 'subroutine';
|
|
|
|
break;
|
|
|
|
case 'cylinder':
|
|
|
|
_shape = 'cylinder';
|
|
|
|
break;
|
|
|
|
case 'group':
|
|
|
|
_shape = 'rect';
|
|
|
|
break;
|
|
|
|
case 'doublecircle':
|
|
|
|
_shape = 'doublecircle';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
_shape = 'rect';
|
|
|
|
}
|
|
|
|
|
|
|
|
// const styles = getStylesFromArray(vertex.styles);
|
|
|
|
const styles = getStylesFromArray([]);
|
|
|
|
|
|
|
|
// Use vertex id as text in the box if no text is provided by the graph definition
|
|
|
|
const vertexText = vertex.label;
|
|
|
|
|
2023-09-05 15:15:08 +02:00
|
|
|
const bounds = vertex.size || { width: 0, height: 0, x: 0, y: 0 };
|
2023-09-05 11:13:27 +02:00
|
|
|
// Add the node
|
|
|
|
const node = {
|
|
|
|
labelStyle: styles.labelStyle,
|
|
|
|
shape: _shape,
|
|
|
|
labelText: vertexText,
|
|
|
|
// labelType: vertex.labelType,
|
|
|
|
rx: radious,
|
|
|
|
ry: radious,
|
|
|
|
class: classStr,
|
|
|
|
style: styles.style,
|
|
|
|
id: vertex.id,
|
|
|
|
// link: vertex.link,
|
|
|
|
// linkTarget: vertex.linkTarget,
|
|
|
|
// tooltip: diagObj.db.getTooltip(vertex.id) || '',
|
|
|
|
// domId: diagObj.db.lookUpDomId(vertex.id),
|
|
|
|
// haveCallback: vertex.haveCallback,
|
|
|
|
// width: vertex.type === 'group' ? 500 : undefined,
|
|
|
|
// dir: vertex.dir,
|
2023-09-05 15:15:08 +02:00
|
|
|
width: bounds.width,
|
|
|
|
height: bounds.height,
|
|
|
|
x: bounds.x,
|
|
|
|
y: bounds.y,
|
|
|
|
positioned,
|
2023-09-05 11:13:27 +02:00
|
|
|
type: vertex.type,
|
|
|
|
// props: vertex.props,
|
2023-10-20 12:30:25 +02:00
|
|
|
padding: padding ?? (getConfig()?.flowchart?.padding || 0),
|
2023-09-05 11:13:27 +02:00
|
|
|
};
|
|
|
|
return node;
|
|
|
|
}
|
2023-09-05 15:15:08 +02:00
|
|
|
type IOperation = (elem: any, block: any, db: any) => Promise<void>;
|
2023-09-05 11:13:27 +02:00
|
|
|
async function calculateBlockSize(elem: any, block: any, db: any) {
|
2023-09-05 15:15:08 +02:00
|
|
|
const node = getNodeFromBlock(block, db, false);
|
2023-10-03 12:56:47 +02:00
|
|
|
if (node.type === 'group') {
|
|
|
|
return;
|
|
|
|
}
|
2023-09-05 11:13:27 +02:00
|
|
|
|
|
|
|
// Add the element to the DOM to size it
|
|
|
|
const nodeEl = await insertNode(elem, node);
|
|
|
|
const boundingBox = nodeEl.node().getBBox();
|
|
|
|
const obj = db.getBlock(node.id);
|
|
|
|
obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
|
|
|
|
db.setBlock(obj);
|
2023-09-05 15:15:08 +02:00
|
|
|
nodeEl.remove();
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
|
2023-10-20 12:30:25 +02:00
|
|
|
export async function insertBlockPositioned(elem: any, block: Block, db: any) {
|
2023-09-05 15:15:08 +02:00
|
|
|
const node = getNodeFromBlock(block, db, true);
|
2023-10-03 12:56:47 +02:00
|
|
|
// if (node.type === 'composite') {
|
|
|
|
// return;
|
|
|
|
// }
|
2023-09-05 15:15:08 +02:00
|
|
|
// Add the element to the DOM to size it
|
2023-10-15 22:55:29 +02:00
|
|
|
const obj = db.getBlock(node.id);
|
2023-10-20 12:30:25 +02:00
|
|
|
if (obj.type !== 'space') {
|
|
|
|
const nodeEl = await insertNode(elem, node);
|
|
|
|
positionNode(node);
|
|
|
|
}
|
2023-09-05 15:15:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function performOperations(
|
|
|
|
elem: ContainerElement,
|
|
|
|
blocks: Block[],
|
|
|
|
db: BlockDB,
|
|
|
|
operation: IOperation
|
|
|
|
) {
|
2023-09-05 11:13:27 +02:00
|
|
|
for (const block of blocks) {
|
2023-09-05 15:15:08 +02:00
|
|
|
await operation(elem, block, db);
|
2023-09-05 11:13:27 +02:00
|
|
|
if (block.children) {
|
2023-09-05 15:15:08 +02:00
|
|
|
await performOperations(elem, block.children, db, operation);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-05 15:15:08 +02:00
|
|
|
export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[], db: BlockDB) {
|
|
|
|
await performOperations(elem, blocks, db, calculateBlockSize);
|
|
|
|
}
|
2023-09-05 11:13:27 +02:00
|
|
|
|
2023-09-05 15:15:08 +02:00
|
|
|
export async function insertBlocks(elem: ContainerElement, blocks: Block[], db: BlockDB) {
|
|
|
|
await performOperations(elem, blocks, db, insertBlockPositioned);
|
2023-09-05 11:13:27 +02:00
|
|
|
}
|