mermaid/packages/mermaid/src/diagrams/block/renderHelpers.ts

182 lines
4.7 KiB
TypeScript
Raw Normal View History

import { getStylesFromArray } from '../../utils.js';
2023-09-14 10:11:43 +02:00
import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
import { getConfig } from '../../config.js';
import { ContainerElement } from 'd3';
import type { Block } from './blockTypes.js';
import { BlockDB } from './blockDB.js';
interface Node {
classes: string;
}
2023-10-03 12:56:47 +02:00
function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
const vertex = block;
let classStr = 'default';
if ((vertex?.classes?.length || 0) > 0) {
classStr = (vertex?.classes || []).join(' ');
}
classStr = classStr + ' flowchart-label';
// We create a SVG label, either by delegating to addHtmlLabel or manually
let radious = 0;
let _shape = '';
let layoutOptions = {};
let padding;
// Set the shape based parameters
switch (vertex.type) {
case 'round':
radious = 5;
_shape = 'rect';
break;
// case 'composite-subgraph':
// radious = 0;
// _shape = 'composite';
// break;
2023-10-03 14:19:08 +02:00
case 'composite':
radious = 0;
2023-10-03 14:19:08 +02:00
_shape = 'composite';
padding = 0;
2023-10-03 14:19:08 +02:00
break;
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 };
// 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,
type: vertex.type,
// props: vertex.props,
padding: padding ?? (getConfig()?.flowchart?.padding || 0),
};
return node;
}
2023-09-05 15:15:08 +02:00
type IOperation = (elem: any, block: any, db: any) => Promise<void>;
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;
}
// 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();
}
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);
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
) {
for (const block of blocks) {
2023-09-05 15:15:08 +02:00
await operation(elem, block, db);
if (block.children) {
2023-09-05 15:15:08 +02:00
await performOperations(elem, block.children, db, operation);
}
}
}
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 15:15:08 +02:00
export async function insertBlocks(elem: ContainerElement, blocks: Block[], db: BlockDB) {
await performOperations(elem, blocks, db, insertBlockPositioned);
}