#5237 Enabling subgraphs using the unified renderer for flowcharts

This commit is contained in:
Knut Sveidqvist
2024-06-07 20:23:44 +02:00
parent a85f36c3be
commit 1b29135cc1
4 changed files with 77 additions and 29 deletions

View File

@@ -84,13 +84,17 @@ stateDiagram-v2
if_state --> True : if n >= 0 if_state --> True : if n >= 0
</pre </pre
> >
<pre id="diagram" class="mermaid2"> <pre id="diagram" class="mermaid">
flowchart LR flowchart LR
A[Start] --> B{Is it?} --> B1 & B2 subgraph Apa
A[Start] --> B
end
Apa --> C
A --> C
</pre </pre
> >
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid2">
%%{init: {"layout": "dagre", "mergeEdges": false} }%% %%{init: {"layout": "dagre", "mergeEdges": false} }%%
flowchart LR flowchart LR
A ==> B(This is B) A ==> B(This is B)
@@ -213,12 +217,12 @@ stateDiagram-v2
mermaid.initialize({ mermaid.initialize({
// theme: 'base', // theme: 'base',
// handdrawnSeed: 12, // handdrawnSeed: 12,
// look: 'handdrawn', look: 'handdrawn',
'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX', // 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
layout: 'dagre', // layout: 'dagre',
// layout: 'elk', // layout: 'elk',
// layout: 'fixed', // layout: 'fixed',
htmlLabels: false, // htmlLabels: false,
flowchart: { titleTopMargin: 10 }, flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat', // fontFamily: 'Caveat',
fontFamily: 'Kalam', fontFamily: 'Kalam',

View File

@@ -775,20 +775,39 @@ export const getData = () => {
// extract(getRootDocV2()); // extract(getRootDocV2());
// const diagramStates = getStates(); // const diagramStates = getStates();
const useRough = config.look === 'handdrawn'; const useRough = config.look === 'handdrawn';
const subGraphs = getSubGraphs();
log.info('Subgraphs - ', subGraphs);
const parentDB = new Map<string, string>();
const subGraphDB = new Map<string, boolean>();
for (let i = subGraphs.length - 1; i >= 0; i--) {
const subGraph = subGraphs[i];
if (subGraph.nodes.length > 0) {
subGraphDB.set(subGraph.id, true);
}
subGraph.nodes.forEach((id) => {
parentDB.set(id, subGraph.id);
});
}
const n = getVertices(); const n = getVertices();
n.forEach((vertex) => { n.forEach((vertex) => {
let parentId = parentDB.get(vertex.id);
let isGroup = subGraphDB.get(vertex.id) || false;
const node: Node = { const node: Node = {
id: vertex.id, id: vertex.id,
label: vertex.text, label: vertex.text,
labelStyle: '', labelStyle: '',
parentId,
padding: config.flowchart?.padding || 8, padding: config.flowchart?.padding || 8,
cssStyles: vertex.styles.join(' '), cssStyles: vertex.styles.join(' '),
cssClasses: vertex.classes.join(' '), cssClasses: vertex.classes.join(' '),
shape: getTypeFromVertex(vertex), shape: getTypeFromVertex(vertex),
dir: vertex.dir, dir: vertex.dir,
domId: vertex.domId, domId: vertex.domId,
type: undefined, type: isGroup ? 'group' : undefined,
isGroup: false, isGroup,
useRough, useRough,
}; };
nodes.push(node); nodes.push(node);
@@ -823,7 +842,6 @@ export const getData = () => {
// console.log('rawEdge SPLIT', rawEdge, index); // console.log('rawEdge SPLIT', rawEdge, index);
edges.push(edge); edges.push(edge);
}); });
console.log('edges SPLIT', edges);
//const useRough = config.look === 'handdrawn'; //const useRough = config.look === 'handdrawn';

View File

@@ -159,10 +159,8 @@ export const validate = (graph) => {
* @param {any} graph * @param {any} graph
*/ */
export const findNonClusterChild = (id, graph) => { export const findNonClusterChild = (id, graph) => {
// const node = graph.node(id);
log.trace('Searching', id); log.trace('Searching', id);
// const children = graph.children(id).reverse(); const children = graph.children(id).reverse();
const children = graph.children(id); //.reverse();
log.trace('Searching children of id ', id, children); log.trace('Searching children of id ', id, children);
if (children.length < 1) { if (children.length < 1) {
log.trace('This is a valid node', id); log.trace('This is a valid node', id);

View File

@@ -8,17 +8,18 @@ import { createText } from '../createText.ts';
import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; import intersectRect from '../rendering-elements/intersect/intersect-rect.js';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts';
import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js';
const rect = (parent, node) => { const rect = (parent, node) => {
log.info('Creating subgraph rect for ', node.id, node); log.info('Creating subgraph rect for ', node.id, node);
const siteConfig = getConfig(); const siteConfig = getConfig();
const { themeVariables, handdrawnSeed } = siteConfig;
const { clusterBkg, clusterBorder } = themeVariables;
let { useRough } = node;
// Add outer g element // Add outer g element
const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id); const shapeSvg = parent.insert('g').attr('class', 'cluster').attr('id', node.id);
// add the rect
const rect = shapeSvg.insert('rect', ':first-child');
const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels); const useHtmlLabels = evaluate(siteConfig.flowchart.htmlLabels);
// Create the label and insert it after the rect // Create the label and insert it after the rect
@@ -44,7 +45,6 @@ const rect = (parent, node) => {
} }
const padding = 0 * node.padding; const padding = 0 * node.padding;
const halfPadding = padding / 2;
const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width; const width = node.width <= bbox.width + padding ? bbox.width + padding : node.width;
if (node.width <= bbox.width + padding) { if (node.width <= bbox.width + padding) {
@@ -53,17 +53,45 @@ const rect = (parent, node) => {
node.diff = -node.padding / 2; node.diff = -node.padding / 2;
} }
log.trace('Data ', node, JSON.stringify(node)); const totalWidth = width + padding;
// center the rect around its coordinate const totalHeight = node.height + padding;
rect const x = node.x - totalWidth / 2;
.attr('style', node.cssStyles) const y = node.y - totalHeight / 2;
.attr('rx', node.rx)
.attr('ry', node.ry)
.attr('x', node.x - width / 2)
.attr('y', node.y - node.height / 2 - halfPadding)
.attr('width', width)
.attr('height', node.height + padding);
log.trace('Data ', node, JSON.stringify(node));
let rect;
if (useRough) {
// @ts-ignore TODO: Fix rough typings
const rc = rough.svg(shapeSvg);
const options = userNodeOverrides(node, {
roughness: 0.7,
fill: clusterBkg,
// fill: 'red',
stroke: clusterBorder,
fillWeight: 3,
seed: handdrawnSeed,
stroke: clusterBorder,
});
const roughNode = rc.path(createRoundedRectPathD(x, y, totalWidth, totalHeight, 0), options);
// console.log('Rough node insert CXC', roughNode);
rect = shapeSvg.insert(() => {
console.log('Rough node insert CXC', roughNode);
return roughNode;
}, ':first-child');
} else {
// add the rect
rect = shapeSvg.insert('rect', ':first-child');
// center the rect around its coordinate
rect
.attr('style', node.cssStyles)
.attr('rx', node.rx)
.attr('ry', node.ry)
.attr('x', x)
.attr('y', y)
.attr('width', totalWidth)
.attr('height', totalHeight);
}
const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig); const { subGraphTitleTopMargin } = getSubGraphTitleMargins(siteConfig);
if (useHtmlLabels) { if (useHtmlLabels) {
labelEl.attr( labelEl.attr(
@@ -303,8 +331,8 @@ const divider = (parent, node) => {
return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } }; return { cluster: shapeSvg, labelBBox: { width: 0, height: 0 } };
}; };
const squareRect = rect;
const shapes = { rect, roundedWithTitle, noteGroup, divider }; const shapes = { rect, squareRect, roundedWithTitle, noteGroup, divider };
let clusterElems = {}; let clusterElems = {};