mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-26 10:49:38 +02:00
#5237 Handling paddings in subgraphs for state diagrams
This commit is contained in:
@@ -302,7 +302,7 @@ export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, alt
|
|||||||
domId: stateDomId(itemId, graphItemCount),
|
domId: stateDomId(itemId, graphItemCount),
|
||||||
type: newNode.type,
|
type: newNode.type,
|
||||||
isGroup: newNode.type === 'group',
|
isGroup: newNode.type === 'group',
|
||||||
padding: 15,
|
padding: 8,
|
||||||
rx: 10,
|
rx: 10,
|
||||||
ry: 10,
|
ry: 10,
|
||||||
useRough,
|
useRough,
|
||||||
@@ -328,7 +328,7 @@ export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, alt
|
|||||||
domId: stateDomId(itemId, graphItemCount, NOTE),
|
domId: stateDomId(itemId, graphItemCount, NOTE),
|
||||||
type: newNode.type,
|
type: newNode.type,
|
||||||
isGroup: newNode.type === 'group',
|
isGroup: newNode.type === 'group',
|
||||||
padding: 15, //getConfig().flowchart.padding
|
padding: 0, //getConfig().flowchart.padding
|
||||||
useRough,
|
useRough,
|
||||||
};
|
};
|
||||||
const groupData = {
|
const groupData = {
|
||||||
@@ -341,7 +341,7 @@ export const dataFetcher = (parent, parsedItem, diagramStates, nodes, edges, alt
|
|||||||
domId: stateDomId(itemId, graphItemCount, PARENT),
|
domId: stateDomId(itemId, graphItemCount, PARENT),
|
||||||
type: 'group',
|
type: 'group',
|
||||||
isGroup: true,
|
isGroup: true,
|
||||||
padding: 0, //getConfig().flowchart.padding
|
padding: 16, //getConfig().flowchart.padding
|
||||||
useRough,
|
useRough,
|
||||||
};
|
};
|
||||||
graphItemCount++;
|
graphItemCount++;
|
||||||
|
@@ -54,7 +54,14 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
if (parentCluster !== undefined) {
|
if (parentCluster !== undefined) {
|
||||||
const data = JSON.parse(JSON.stringify(parentCluster.clusterData));
|
const data = JSON.parse(JSON.stringify(parentCluster.clusterData));
|
||||||
// data.clusterPositioning = true;
|
// data.clusterPositioning = true;
|
||||||
log.info('Setting data for cluster XXX (', v, ') ', data, parentCluster);
|
log.trace(
|
||||||
|
'Setting data for parent cluster XXX\n Node.id = ',
|
||||||
|
v,
|
||||||
|
'\n data=',
|
||||||
|
data.height,
|
||||||
|
'\nParent cluster',
|
||||||
|
parentCluster.height
|
||||||
|
);
|
||||||
graph.setNode(parentCluster.id, data);
|
graph.setNode(parentCluster.id, data);
|
||||||
if (!graph.parent(v)) {
|
if (!graph.parent(v)) {
|
||||||
log.trace('Setting parent', v, parentCluster.id);
|
log.trace('Setting parent', v, parentCluster.id);
|
||||||
@@ -64,7 +71,8 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v)));
|
log.info('(Insert) Node XXX' + v + ': ' + JSON.stringify(graph.node(v)));
|
||||||
if (node && node.clusterNode) {
|
if (node && node.clusterNode) {
|
||||||
// const children = graph.children(v);
|
// const children = graph.children(v);
|
||||||
log.info('Cluster identified', v, node.width, graph.node(v));
|
log.info('Cluster identified XXX', v, node.width, graph.node(v));
|
||||||
|
// "o" will contain the full cluster not just the children
|
||||||
const o = await recursiveRender(
|
const o = await recursiveRender(
|
||||||
nodes,
|
nodes,
|
||||||
node.graph,
|
node.graph,
|
||||||
@@ -76,10 +84,18 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
const newEl = o.elem;
|
const newEl = o.elem;
|
||||||
updateNodeBounds(node, newEl);
|
updateNodeBounds(node, newEl);
|
||||||
node.diff = o.diff || 0;
|
node.diff = o.diff || 0;
|
||||||
log.info('Node bounds (abc123)', v, node, node.width, node.x, node.y);
|
log.trace(
|
||||||
|
'New compound node after recursive render XAX',
|
||||||
|
v,
|
||||||
|
'width',
|
||||||
|
// node,
|
||||||
|
node.width,
|
||||||
|
'height',
|
||||||
|
node.height
|
||||||
|
// node.x,
|
||||||
|
// node.y
|
||||||
|
);
|
||||||
setNodeElem(newEl, node);
|
setNodeElem(newEl, node);
|
||||||
|
|
||||||
log.warn('Recursive render complete ', newEl, node);
|
|
||||||
} else {
|
} else {
|
||||||
if (graph.children(v).length > 0) {
|
if (graph.children(v).length > 0) {
|
||||||
// This is a cluster but not to be rendered recursively
|
// This is a cluster but not to be rendered recursively
|
||||||
@@ -89,7 +105,7 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node };
|
clusterDb[node.id] = { id: findNonClusterChild(node.id, graph), node };
|
||||||
// insertCluster(clusters, graph.node(v));
|
// insertCluster(clusters, graph.node(v));
|
||||||
} else {
|
} else {
|
||||||
log.info('Node - the non recursive path', v, node.id, node);
|
log.trace('Node - the non recursive path XAX', v, node.id, node);
|
||||||
await insertNode(nodes, graph.node(v), dir);
|
await insertNode(nodes, graph.node(v), dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,20 +129,26 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
graph.edges().forEach(function (e) {
|
graph.edges().forEach(function (e) {
|
||||||
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
||||||
});
|
});
|
||||||
log.info('#############################################');
|
|
||||||
log.info('### Layout ###');
|
log.info('############################################# XXX');
|
||||||
log.info('#############################################');
|
log.info('### Layout ### XXX');
|
||||||
log.info(graph);
|
log.info('############################################# XXX');
|
||||||
|
|
||||||
dagreLayout(graph);
|
dagreLayout(graph);
|
||||||
|
|
||||||
log.info('Graph after layout:', graphlibJson.write(graph));
|
log.info('Graph after layout:', graphlibJson.write(graph));
|
||||||
// Move the nodes to the correct place
|
// Move the nodes to the correct place
|
||||||
let diff = 0;
|
let diff = 0;
|
||||||
const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
log.info('Need the size here XAX', graph.node('T1')?.height);
|
||||||
|
let { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
||||||
|
subGraphTitleTotalMargin = 0;
|
||||||
sortNodesByHierarchy(graph).forEach(function (v) {
|
sortNodesByHierarchy(graph).forEach(function (v) {
|
||||||
const node = graph.node(v);
|
const node = graph.node(v);
|
||||||
log.info('Position ' + v + ': ' + JSON.stringify(graph.node(v)));
|
const p = graph.node(node?.parentId);
|
||||||
|
subGraphTitleTotalMargin = p?.offsetY || subGraphTitleTotalMargin;
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
'Position ' + v + ': (' + node.x,
|
'Position XAX' + v + ': (' + node.x,
|
||||||
',' + node.y,
|
',' + node.y,
|
||||||
') width: ',
|
') width: ',
|
||||||
node.width,
|
node.width,
|
||||||
@@ -134,19 +156,55 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
node.height
|
node.height
|
||||||
);
|
);
|
||||||
if (node && node.clusterNode) {
|
if (node && node.clusterNode) {
|
||||||
// clusterDb[node.id].node = node;
|
const parent = graph.node(node.parentId);
|
||||||
node.y += subGraphTitleTotalMargin;
|
node.y += 2;
|
||||||
|
node.x -= 8;
|
||||||
|
log.trace('A tainted cluster node XAX', v, node.id, node.width, node.height, node.x, node.y);
|
||||||
|
clusterDb[node.id].node = node;
|
||||||
|
// node.y += subGraphTitleTotalMargin - 10;
|
||||||
|
node.y -= (node.offsetY || 0) / 2;
|
||||||
positionNode(node);
|
positionNode(node);
|
||||||
} else {
|
} else {
|
||||||
// Non cluster node
|
// Non cluster node
|
||||||
if (graph.children(v).length > 0) {
|
if (graph.children(v).length > 0) {
|
||||||
// A cluster in the non-recursive way
|
node.height += 0;
|
||||||
// positionCluster(node);
|
const parent = graph.node(node.parentId);
|
||||||
node.height += subGraphTitleTotalMargin;
|
node.y += (node.offsetY || 0) / 2;
|
||||||
insertCluster(clusters, node);
|
insertCluster(clusters, node);
|
||||||
|
|
||||||
|
// A cluster in the non-recursive way
|
||||||
|
log.trace(
|
||||||
|
'A pure cluster node with children XAX',
|
||||||
|
v,
|
||||||
|
node.id,
|
||||||
|
node.width,
|
||||||
|
node.height,
|
||||||
|
node.x,
|
||||||
|
node.y,
|
||||||
|
'offset',
|
||||||
|
parent?.offsetY
|
||||||
|
);
|
||||||
clusterDb[node.id].node = node;
|
clusterDb[node.id].node = node;
|
||||||
} else {
|
} else {
|
||||||
node.y += subGraphTitleTotalMargin / 2;
|
const parent = graph.node(node.parentId);
|
||||||
|
node.y += (parent?.offsetY || 0) / 2;
|
||||||
|
log.trace(
|
||||||
|
'A regular node XAX - using the padding',
|
||||||
|
v,
|
||||||
|
node.id,
|
||||||
|
'parent',
|
||||||
|
node.parentId,
|
||||||
|
node.width,
|
||||||
|
node.height,
|
||||||
|
node.x,
|
||||||
|
node.y,
|
||||||
|
'offsetY',
|
||||||
|
node.offsetY,
|
||||||
|
'parent',
|
||||||
|
parent,
|
||||||
|
node
|
||||||
|
);
|
||||||
|
|
||||||
positionNode(node);
|
positionNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,9 +227,14 @@ const recursiveRender = async (_elem, graph, diagramType, id, parentCluster, sit
|
|||||||
diff = n.diff;
|
diff = n.diff;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
log.trace('Returning from recursive render XAX', elem, diff);
|
||||||
return { elem, diff };
|
return { elem, diff };
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* ###############################################################
|
||||||
|
* Render the graph
|
||||||
|
* ###############################################################
|
||||||
|
*/
|
||||||
export const render = async (data4Layout, svg, element) => {
|
export const render = async (data4Layout, svg, element) => {
|
||||||
// Create the input mermaid.graph
|
// Create the input mermaid.graph
|
||||||
const graph = new graphlib.Graph({
|
const graph = new graphlib.Graph({
|
||||||
@@ -223,13 +286,3 @@ export const render = async (data4Layout, svg, element) => {
|
|||||||
siteConfig
|
siteConfig
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// const shapeDefinitions = {};
|
|
||||||
// export const addShape = ({ shapeType: fun }) => {
|
|
||||||
// shapeDefinitions[shapeType] = fun;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const arrowDefinitions = {};
|
|
||||||
// export const addArrow = ({ arrowType: fun }) => {
|
|
||||||
// arrowDefinitions[arrowType] = fun;
|
|
||||||
// };
|
|
||||||
|
@@ -247,6 +247,8 @@ const roundedWithTitle = (parent, node) => {
|
|||||||
|
|
||||||
const rectBox = rect.node().getBBox();
|
const rectBox = rect.node().getBBox();
|
||||||
node.height = rectBox.height;
|
node.height = rectBox.height;
|
||||||
|
node.offsetX = 0;
|
||||||
|
node.offsetY = 20;
|
||||||
|
|
||||||
node.intersect = function (point) {
|
node.intersect = function (point) {
|
||||||
return intersectRect(node, point);
|
return intersectRect(node, point);
|
||||||
@@ -292,8 +294,9 @@ const divider = (parent, node) => {
|
|||||||
}
|
}
|
||||||
const rectBox = rect.node().getBBox();
|
const rectBox = rect.node().getBBox();
|
||||||
node.width = rectBox.width;
|
node.width = rectBox.width;
|
||||||
node.height = rectBox.height;
|
node.height = rectBox.height - node.padding;
|
||||||
node.diff = -node.padding / 2;
|
node.diff = 0; //-node.padding / 2;
|
||||||
|
node.offsetY = 0;
|
||||||
node.intersect = function (point) {
|
node.intersect = function (point) {
|
||||||
return intersectRect(node, point);
|
return intersectRect(node, point);
|
||||||
};
|
};
|
||||||
@@ -306,7 +309,6 @@ const shapes = { rect, roundedWithTitle, noteGroup, divider };
|
|||||||
let clusterElems = {};
|
let clusterElems = {};
|
||||||
|
|
||||||
export const insertCluster = (elem, node) => {
|
export const insertCluster = (elem, node) => {
|
||||||
log.trace('Inserting cluster');
|
|
||||||
const shape = node.shape || 'rect';
|
const shape = node.shape || 'rect';
|
||||||
const cluster = shapes[shape](elem, node);
|
const cluster = shapes[shape](elem, node);
|
||||||
clusterElems[node.id] = cluster;
|
clusterElems[node.id] = cluster;
|
||||||
|
@@ -75,16 +75,12 @@ export const positionNode = (node) => {
|
|||||||
node,
|
node,
|
||||||
'translate(' + (node.x - node.width / 2 - 5) + ', ' + node.width / 2 + ')'
|
'translate(' + (node.x - node.width / 2 - 5) + ', ' + node.width / 2 + ')'
|
||||||
);
|
);
|
||||||
const padding = 8;
|
|
||||||
const diff = node.diff || 0;
|
const diff = 0;
|
||||||
if (node.clusterNode) {
|
if (node.clusterNode) {
|
||||||
el.attr(
|
el.attr(
|
||||||
'transform',
|
'transform',
|
||||||
'translate(' +
|
'translate(' + (node.x + diff - node.width / 2) + ', ' + (node.y - node.height / 2) + ')'
|
||||||
(node.x + diff - node.width / 2) +
|
|
||||||
', ' +
|
|
||||||
(node.y - node.height / 2 - padding) +
|
|
||||||
')'
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
|
el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
|
||||||
|
@@ -100,6 +100,11 @@ properties:
|
|||||||
type: integer
|
type: integer
|
||||||
default: 500
|
default: 500
|
||||||
minimum: 0
|
minimum: 0
|
||||||
|
mergeEdges:
|
||||||
|
description: |
|
||||||
|
Elk specific option that allows edge egdes to share path where it convenient. It can make for pretty diagrams but can also make it harder to read the diagram.
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
darkMode:
|
darkMode:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
Reference in New Issue
Block a user