mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-08 01:56:42 +02:00
#1295 Fix for intersection calculation for edges to clusters and adding concurrency in stateDiagrams as clusters
This commit is contained in:
@@ -32,13 +32,31 @@
|
|||||||
G-->c
|
G-->c
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 50%; height: 20%;">
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
flowchart LR
|
stateDiagram-v2
|
||||||
subgraph id1 [Test]
|
[*] --> monkey
|
||||||
b
|
state monkey {
|
||||||
end
|
Sitting
|
||||||
a-->id1
|
--
|
||||||
|
Eating
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid mermaid-apa" style="width: 100%; height: 20%;">
|
<div class="mermaid2" style="width: 50%; height: 20%;">
|
||||||
|
stateDiagram-v2
|
||||||
|
state Active {
|
||||||
|
[*] --> NumLockOff
|
||||||
|
NumLockOff --> NumLockOn : EvNumLockPressed
|
||||||
|
NumLockOn --> NumLockOff : EvNumLockPressed
|
||||||
|
--
|
||||||
|
[*] --> CapsLockOff
|
||||||
|
CapsLockOff --> CapsLockOn : EvCapsLockPressed
|
||||||
|
CapsLockOn --> CapsLockOff : EvCapsLockPressed
|
||||||
|
--
|
||||||
|
[*] --> ScrollLockOff
|
||||||
|
ScrollLockOff --> ScrollLockOn : EvCapsLockPressed
|
||||||
|
ScrollLockOn --> ScrollLockOff : EvCapsLockPressed
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="mermaid2 mermaid-apa" style="width: 100%; height: 20%;">
|
||||||
stateDiagram
|
stateDiagram
|
||||||
[*] --> Still
|
[*] --> Still
|
||||||
Still --> [*]
|
Still --> [*]
|
||||||
@@ -52,15 +70,39 @@
|
|||||||
Moving --> Crash
|
Moving --> Crash
|
||||||
Crash --> [*]
|
Crash --> [*]
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mermaid2" style="width: 100%; height: 100%;">
|
||||||
|
stateDiagram-v2
|
||||||
|
[*] --> First
|
||||||
|
First --> Second
|
||||||
|
% First --> Third
|
||||||
|
|
||||||
|
state First {
|
||||||
|
[*] --> fir
|
||||||
|
fir --> [*]
|
||||||
|
}
|
||||||
|
state Second {
|
||||||
|
[*] --> sec
|
||||||
|
sec --> [*]
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div class="mermaid" style="width: 100%; height: 100%;">
|
<div class="mermaid" style="width: 100%; height: 100%;">
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
State1: The state with a note
|
[*] --> First
|
||||||
note right of State1
|
First --> Second
|
||||||
Important information! You can write
|
First --> Third
|
||||||
notes.
|
|
||||||
end note
|
state First {
|
||||||
State1 --> State2
|
[*] --> fir
|
||||||
note left of State2 : This is the note to the left.
|
fir --> [*]
|
||||||
|
}
|
||||||
|
state Second {
|
||||||
|
[*] --> sec
|
||||||
|
sec --> [*]
|
||||||
|
}
|
||||||
|
state Third {
|
||||||
|
[*] --> thi
|
||||||
|
thi --> [*]
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="mermaid2" style="width: 100%; height: 100%;">
|
<div class="mermaid2" style="width: 100%; height: 100%;">
|
||||||
stateDiagram-v2
|
stateDiagram-v2
|
||||||
|
@@ -7,12 +7,10 @@ Explains the representation of various objects used to render the flow charts an
|
|||||||
Sample object:
|
Sample object:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"labelType":"svg",
|
|
||||||
"labelStyle":"",
|
|
||||||
"shape":"rect",
|
"shape":"rect",
|
||||||
"label":{},
|
|
||||||
"labelText":"Test",
|
"labelText":"Test",
|
||||||
"rx":0,"ry":0,
|
"rx":0,
|
||||||
|
"ry":0,
|
||||||
"class":"default",
|
"class":"default",
|
||||||
"style":"",
|
"style":"",
|
||||||
"id":"Test",
|
"id":"Test",
|
||||||
@@ -24,18 +22,16 @@ This is set by the renderer of the diagram and insert the data that the wrapper
|
|||||||
|
|
||||||
| property | description |
|
| property | description |
|
||||||
| ---------- | ----------------------------------------------------------------------------------------------------------- |
|
| ---------- | ----------------------------------------------------------------------------------------------------------- |
|
||||||
| labelType | If the label should be html label or a svg label. Should we continue to support both? |
|
| labelStyle | Css styles for the label. User for instance for stylling the labels for clusters |
|
||||||
| labelStyle | Css styles for the label. Not currently used. |
|
| shape | The shape of the node. |
|
||||||
| shape | The shape of the node. Currently on rect is suppoerted. This will change. |
|
|
||||||
| label | ?? |
|
|
||||||
| labelText | The text on the label |
|
| labelText | The text on the label |
|
||||||
| rx | The corner radius - maybe part of the shape instead? |
|
| rx | The corner radius - maybe part of the shape instead? Used for rects. |
|
||||||
| ry | The corner radius - maybe part of the shape instead? |
|
| ry | The corner radius - maybe part of the shape instead? Used for rects. |
|
||||||
| class | Class to be set for the shape |
|
| classes | Classes to be set for the shape. Not used |
|
||||||
| style | Css styles for the actual shape |
|
| style | Css styles for the actual shape |
|
||||||
| id | id of the shape |
|
| id | id of the shape |
|
||||||
| type | if set to group then this node indicates *a cluster*. |
|
| type | if set to group then this node indicates *a cluster*. |
|
||||||
| padding | Padding. Passed from the renderr as this might differ between react for different diagrams. Maybe obsolete. |
|
| padding | Padding. Passed from the render as this might differ between different diagrams. Maybe obsolete. |
|
||||||
|
|
||||||
|
|
||||||
# edge
|
# edge
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
const createLabel = (vertexText, style) => {
|
const createLabel = (vertexText, style) => {
|
||||||
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
|
||||||
svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
|
||||||
|
let rows = [];
|
||||||
const rows = vertexText.split(/\n|<br\s*\/?>/gi);
|
if (vertexText) {
|
||||||
|
rows = vertexText.split(/\n|<br\s*\/?>/gi);
|
||||||
|
}
|
||||||
|
|
||||||
for (let j = 0; j < rows.length; j++) {
|
for (let j = 0; j < rows.length; j++) {
|
||||||
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
|
||||||
|
@@ -63,34 +63,17 @@ const outsideNode = (node, point) => {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
// const intersection = (node, outsidePoint, insidePoint) => {
|
|
||||||
// const x = node.x;
|
|
||||||
// const y = node.y;
|
|
||||||
|
|
||||||
// const dx = Math.abs(x - insidePoint.x);
|
|
||||||
// const w = node.width / 2;
|
|
||||||
// let r = w - dx;
|
|
||||||
// const dy = Math.abs(y - insidePoint.y);
|
|
||||||
// const h = node.height / 2;
|
|
||||||
// const q = h - dy;
|
|
||||||
|
|
||||||
// const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
|
||||||
// const R = Math.abs(outsidePoint.x - insidePoint.x);
|
|
||||||
// r = (R * q) / Q;
|
|
||||||
|
|
||||||
// return { x: insidePoint.x + r, y: insidePoint.y + q };
|
|
||||||
// };
|
|
||||||
const intersection = (node, outsidePoint, insidePoint) => {
|
const intersection = (node, outsidePoint, insidePoint) => {
|
||||||
// logger.info('intersection', outsidePoint, insidePoint, node);
|
logger.info('intersection o:', outsidePoint, ' i:', insidePoint, node);
|
||||||
const x = node.x;
|
const x = node.x;
|
||||||
const y = node.y;
|
const y = node.y;
|
||||||
|
|
||||||
const dx = Math.abs(x - insidePoint.x);
|
const dx = Math.abs(x - insidePoint.x);
|
||||||
const w = node.width / 2;
|
const w = node.width / 2;
|
||||||
let r = w - dx;
|
let r = insidePoint.x < outsidePoint.x ? w - dx : w + dx;
|
||||||
const dy = Math.abs(y - insidePoint.y);
|
const dy = Math.abs(y - insidePoint.y);
|
||||||
const h = node.height / 2;
|
const h = node.height / 2;
|
||||||
let q = h - dy;
|
let q = insidePoint.y < outsidePoint.y ? h - dy : h - dy;
|
||||||
|
|
||||||
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
const Q = Math.abs(outsidePoint.y - insidePoint.y);
|
||||||
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
const R = Math.abs(outsidePoint.x - insidePoint.x);
|
||||||
@@ -105,9 +88,10 @@ const intersection = (node, outsidePoint, insidePoint) => {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
q = (Q * r) / R;
|
q = (Q * r) / R;
|
||||||
|
r = (R * q) / Q;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x - r,
|
x: insidePoint.x < outsidePoint.x ? insidePoint.x + r : insidePoint.x + dx - w,
|
||||||
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
y: insidePoint.y < outsidePoint.y ? insidePoint.y + q : insidePoint.y - q
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -117,8 +101,8 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
logger.info('\n\n\n\n');
|
logger.info('\n\n\n\n');
|
||||||
let points = edge.points;
|
let points = edge.points;
|
||||||
if (edge.toCluster) {
|
if (edge.toCluster) {
|
||||||
// logger.info('edge', edge);
|
logger.info('edge', edge);
|
||||||
// logger.info('to cluster', clusterDb[edge.toCluster]);
|
logger.info('to cluster', clusterDb[edge.toCluster]);
|
||||||
points = [];
|
points = [];
|
||||||
let lastPointOutside;
|
let lastPointOutside;
|
||||||
let isInside = false;
|
let isInside = false;
|
||||||
@@ -126,13 +110,12 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
const node = clusterDb[edge.toCluster].node;
|
const node = clusterDb[edge.toCluster].node;
|
||||||
|
|
||||||
if (!outsideNode(node, point) && !isInside) {
|
if (!outsideNode(node, point) && !isInside) {
|
||||||
// logger.info('inside', edge.toCluster, point);
|
logger.info('inside', edge.toCluster, point, lastPointOutside);
|
||||||
|
|
||||||
// First point inside the rect
|
// First point inside the rect
|
||||||
const insterection = intersection(node, lastPointOutside, point);
|
const insterection = intersection(node, lastPointOutside, point);
|
||||||
// logger.info('intersect', inter.rect(node, lastPointOutside));
|
logger.info('intersect', insterection);
|
||||||
points.push(insterection);
|
points.push(insterection);
|
||||||
// points.push(insterection);
|
|
||||||
isInside = true;
|
isInside = true;
|
||||||
} else {
|
} else {
|
||||||
if (!isInside) points.push(point);
|
if (!isInside) points.push(point);
|
||||||
@@ -142,8 +125,8 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (edge.fromCluster) {
|
if (edge.fromCluster) {
|
||||||
// logger.info('edge', edge);
|
logger.info('edge', edge);
|
||||||
// logger.info('from cluster', clusterDb[edge.toCluster]);
|
logger.info('from cluster', clusterDb[edge.toCluster]);
|
||||||
const updatedPoints = [];
|
const updatedPoints = [];
|
||||||
let lastPointOutside;
|
let lastPointOutside;
|
||||||
let isInside = false;
|
let isInside = false;
|
||||||
@@ -152,7 +135,7 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
const node = clusterDb[edge.fromCluster].node;
|
const node = clusterDb[edge.fromCluster].node;
|
||||||
|
|
||||||
if (!outsideNode(node, point) && !isInside) {
|
if (!outsideNode(node, point) && !isInside) {
|
||||||
// logger.info('inside', edge.toCluster, point);
|
logger.info('inside', edge.toCluster, point);
|
||||||
|
|
||||||
// First point inside the rect
|
// First point inside the rect
|
||||||
const insterection = intersection(node, lastPointOutside, point);
|
const insterection = intersection(node, lastPointOutside, point);
|
||||||
@@ -162,7 +145,7 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
isInside = true;
|
isInside = true;
|
||||||
} else {
|
} else {
|
||||||
// at the outside
|
// at the outside
|
||||||
// logger.info('Outside point', point);
|
logger.info('Outside point', point);
|
||||||
if (!isInside) updatedPoints.unshift(point);
|
if (!isInside) updatedPoints.unshift(point);
|
||||||
}
|
}
|
||||||
lastPointOutside = point;
|
lastPointOutside = point;
|
||||||
@@ -170,10 +153,6 @@ export const insertEdge = function(elem, edge, clusterDb, diagramType) {
|
|||||||
points = updatedPoints;
|
points = updatedPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
// logger.info('Poibts', points);
|
|
||||||
|
|
||||||
// logger.info('Edge', edge);
|
|
||||||
|
|
||||||
// The data for our line
|
// The data for our line
|
||||||
const lineData = points.filter(p => !Number.isNaN(p.y));
|
const lineData = points.filter(p => !Number.isNaN(p.y));
|
||||||
|
|
||||||
|
@@ -7,8 +7,28 @@ import { logger } from '../logger';
|
|||||||
|
|
||||||
let clusterDb = {};
|
let clusterDb = {};
|
||||||
|
|
||||||
const translateClusterId = id => {
|
const getAnchorId = (id, graph, nodes) => {
|
||||||
if (clusterDb[id]) return clusterDb[id].id;
|
// Only insert an achor once
|
||||||
|
if (clusterDb[id]) {
|
||||||
|
// if (!clusterDb[id].inserted) {
|
||||||
|
// // Create anchor node for cluster
|
||||||
|
// const anchorData = {
|
||||||
|
// shape: 'start',
|
||||||
|
// labelText: '',
|
||||||
|
// classes: '',
|
||||||
|
// style: '',
|
||||||
|
// id: id + '_anchor',
|
||||||
|
// type: 'anchor',
|
||||||
|
// padding: 0
|
||||||
|
// };
|
||||||
|
// insertNode(nodes, anchorData);
|
||||||
|
|
||||||
|
// graph.setNode(anchorData.id, anchorData);
|
||||||
|
// graph.setParent(anchorData.id, id);
|
||||||
|
// clusterDb[id].inserted = true;
|
||||||
|
// }
|
||||||
|
return clusterDb[id].id;
|
||||||
|
}
|
||||||
return id;
|
return id;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -24,24 +44,24 @@ export const render = (elem, graph, markers, diagramtype, id) => {
|
|||||||
const edgeLabels = elem.insert('g').attr('class', 'edgeLabels');
|
const edgeLabels = elem.insert('g').attr('class', 'edgeLabels');
|
||||||
const nodes = elem.insert('g').attr('class', 'nodes');
|
const nodes = elem.insert('g').attr('class', 'nodes');
|
||||||
|
|
||||||
logger.warn('graph', graph);
|
|
||||||
|
|
||||||
// Insert nodes, this will insert them into the dom and each node will get a size. The size is updated
|
// Insert nodes, this will insert them into the dom and each node will get a size. The size is updated
|
||||||
// to the abstract node and is later used by dagre for the layout
|
// to the abstract node and is later used by dagre for the layout
|
||||||
graph.nodes().forEach(function(v) {
|
graph.nodes().forEach(function(v) {
|
||||||
const node = graph.node(v);
|
const node = graph.node(v);
|
||||||
logger.warn('Node ' + v + ': ' + JSON.stringify(graph.node(v)));
|
logger.info('Node ' + v + ': ' + JSON.stringify(graph.node(v)));
|
||||||
if (node.type !== 'group') {
|
if (node.type !== 'group') {
|
||||||
insertNode(nodes, graph.node(v));
|
insertNode(nodes, graph.node(v));
|
||||||
} else {
|
} else {
|
||||||
// const width = getClusterTitleWidth(clusters, node);
|
// const width = getClusterTitleWidth(clusters, node);
|
||||||
const children = graph.children(v);
|
const children = graph.children(v);
|
||||||
|
|
||||||
logger.info('Cluster identified', node.id, children[0]);
|
logger.info('Cluster identified', node.id, children[0]);
|
||||||
// nodes2expand.push({ id: children[0], width });
|
// nodes2expand.push({ id: children[0], width });
|
||||||
clusterDb[node.id] = { id: children[0] };
|
clusterDb[node.id] = { id: children[0] };
|
||||||
logger.info('Clusters ', clusterDb);
|
// clusterDb[node.id] = { id: node.id + '_anchor' };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
logger.info('Clusters ', clusterDb);
|
||||||
|
|
||||||
// Insert labels, this will insert them into the dom so that the width can be calculated
|
// Insert labels, this will insert them into the dom so that the width can be calculated
|
||||||
// Also figure out which edges point to/from clusters and adjust them accordingly
|
// Also figure out which edges point to/from clusters and adjust them accordingly
|
||||||
@@ -49,21 +69,37 @@ export const render = (elem, graph, markers, diagramtype, id) => {
|
|||||||
// TODO: pick optimal child in the cluster to us as link anchor
|
// TODO: pick optimal child in the cluster to us as link anchor
|
||||||
graph.edges().forEach(function(e) {
|
graph.edges().forEach(function(e) {
|
||||||
const edge = graph.edge(e);
|
const edge = graph.edge(e);
|
||||||
logger.warn('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
logger.trace('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
||||||
// logger.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(graph.edge(e)));
|
logger.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(graph.edge(e)));
|
||||||
const v = translateClusterId(e.v);
|
|
||||||
const w = translateClusterId(e.w);
|
let v = e.v;
|
||||||
if (v !== e.v || w !== e.w) {
|
let w = e.w;
|
||||||
|
// Check if link is either from or to a cluster
|
||||||
|
logger.info(
|
||||||
|
'Fix',
|
||||||
|
clusterDb,
|
||||||
|
'ids:',
|
||||||
|
e.v,
|
||||||
|
e.w,
|
||||||
|
'Translateing: ',
|
||||||
|
clusterDb[e.v],
|
||||||
|
clusterDb[e.w]
|
||||||
|
);
|
||||||
|
if (clusterDb[e.v] || clusterDb[e.w]) {
|
||||||
|
logger.info('Fixing and trixing - rwemoving', e.v, e.w, e.name);
|
||||||
|
v = getAnchorId(e.v, graph, nodes);
|
||||||
|
w = getAnchorId(e.w, graph, nodes);
|
||||||
graph.removeEdge(e.v, e.w, e.name);
|
graph.removeEdge(e.v, e.w, e.name);
|
||||||
if (v !== e.v) edge.fromCluster = e.v;
|
if (v !== e.v) edge.fromCluster = e.v;
|
||||||
if (w !== e.w) edge.toCluster = e.w;
|
if (w !== e.w) edge.toCluster = e.w;
|
||||||
|
logger.info('Fixing Replacing with', v, w, e.name);
|
||||||
graph.setEdge(v, w, edge, e.name);
|
graph.setEdge(v, w, edge, e.name);
|
||||||
}
|
}
|
||||||
insertEdgeLabel(edgeLabels, edge);
|
insertEdgeLabel(edgeLabels, edge);
|
||||||
});
|
});
|
||||||
|
|
||||||
graph.edges().forEach(function(e) {
|
graph.edges().forEach(function(e) {
|
||||||
logger.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
logger.trace('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(e));
|
||||||
});
|
});
|
||||||
logger.info('#############################################');
|
logger.info('#############################################');
|
||||||
logger.info('### Layout ###');
|
logger.info('### Layout ###');
|
||||||
@@ -74,7 +110,7 @@ export const render = (elem, graph, markers, diagramtype, id) => {
|
|||||||
// Move the nodes to the correct place
|
// Move the nodes to the correct place
|
||||||
graph.nodes().forEach(function(v) {
|
graph.nodes().forEach(function(v) {
|
||||||
const node = graph.node(v);
|
const node = graph.node(v);
|
||||||
logger.info('Node ' + v + ': ' + JSON.stringify(graph.node(v)));
|
logger.trace('Node ' + v + ': ' + JSON.stringify(graph.node(v)));
|
||||||
if (node.type !== 'group') {
|
if (node.type !== 'group') {
|
||||||
positionNode(node);
|
positionNode(node);
|
||||||
} else {
|
} else {
|
||||||
@@ -86,7 +122,7 @@ export const render = (elem, graph, markers, diagramtype, id) => {
|
|||||||
// Move the edge labels to the correct place after layout
|
// Move the edge labels to the correct place after layout
|
||||||
graph.edges().forEach(function(e) {
|
graph.edges().forEach(function(e) {
|
||||||
const edge = graph.edge(e);
|
const edge = graph.edge(e);
|
||||||
logger.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
logger.trace('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
|
||||||
|
|
||||||
insertEdge(edgePaths, edge, clusterDb, diagramtype);
|
insertEdge(edgePaths, edge, clusterDb, diagramtype);
|
||||||
positionEdgeLabel(edge);
|
positionEdgeLabel(edge);
|
||||||
|
@@ -130,10 +130,8 @@ export const addVertices = function(vert, g, svgId) {
|
|||||||
}
|
}
|
||||||
// Add the node
|
// Add the node
|
||||||
g.setNode(vertex.id, {
|
g.setNode(vertex.id, {
|
||||||
labelType: 'svg',
|
|
||||||
labelStyle: styles.labelStyle,
|
labelStyle: styles.labelStyle,
|
||||||
shape: _shape,
|
shape: _shape,
|
||||||
label: vertexNode,
|
|
||||||
labelText: vertexText,
|
labelText: vertexText,
|
||||||
rx: radious,
|
rx: radious,
|
||||||
ry: radious,
|
ry: radious,
|
||||||
@@ -146,10 +144,8 @@ export const addVertices = function(vert, g, svgId) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
logger.info('setNode', {
|
logger.info('setNode', {
|
||||||
labelType: 'svg',
|
|
||||||
labelStyle: styles.labelStyle,
|
labelStyle: styles.labelStyle,
|
||||||
shape: _shape,
|
shape: _shape,
|
||||||
label: vertexNode,
|
|
||||||
labelText: vertexText,
|
labelText: vertexText,
|
||||||
rx: radious,
|
rx: radious,
|
||||||
ry: radious,
|
ry: radious,
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
import { logger } from '../../logger';
|
import { logger } from '../../logger';
|
||||||
|
import { generateId } from '../../utils';
|
||||||
|
|
||||||
|
const clone = o => JSON.parse(JSON.stringify(o));
|
||||||
|
|
||||||
let rootDoc = [];
|
let rootDoc = [];
|
||||||
const setRootDoc = o => {
|
const setRootDoc = o => {
|
||||||
@@ -22,6 +25,34 @@ const docTranslator = (parent, node, first) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.doc) {
|
if (node.doc) {
|
||||||
|
const doc = [];
|
||||||
|
// Check for concurrency
|
||||||
|
let i = 0;
|
||||||
|
let currentDoc = [];
|
||||||
|
for (i = 0; i < node.doc.length; i++) {
|
||||||
|
if (node.doc[i].type === 'divider') {
|
||||||
|
// debugger;
|
||||||
|
const newNode = clone(node.doc[i]);
|
||||||
|
newNode.doc = clone(currentDoc);
|
||||||
|
doc.push(newNode);
|
||||||
|
currentDoc = [];
|
||||||
|
} else {
|
||||||
|
currentDoc.push(node.doc[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If any divider was encountered
|
||||||
|
if (doc.length > 0 && currentDoc.length > 0) {
|
||||||
|
const newNode = {
|
||||||
|
stmt: 'state',
|
||||||
|
id: generateId(),
|
||||||
|
type: 'divider',
|
||||||
|
doc: clone(currentDoc)
|
||||||
|
};
|
||||||
|
doc.push(clone(newNode));
|
||||||
|
node.doc = doc;
|
||||||
|
}
|
||||||
|
|
||||||
node.doc.forEach(docNode => docTranslator(node, docNode, true));
|
node.doc.forEach(docNode => docTranslator(node, docNode, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,8 +62,14 @@ const getRootDocV2 = () => {
|
|||||||
return { id: 'root', doc: rootDoc };
|
return { id: 'root', doc: rootDoc };
|
||||||
};
|
};
|
||||||
|
|
||||||
const extract = doc => {
|
const extract = _doc => {
|
||||||
// const res = { states: [], relations: [] };
|
// const res = { states: [], relations: [] };
|
||||||
|
let doc;
|
||||||
|
if (_doc.doc) {
|
||||||
|
doc = _doc.doc;
|
||||||
|
} else {
|
||||||
|
doc = _doc;
|
||||||
|
}
|
||||||
// let doc = root.doc;
|
// let doc = root.doc;
|
||||||
// if (!doc) {
|
// if (!doc) {
|
||||||
// doc = root;
|
// doc = root;
|
||||||
@@ -40,6 +77,8 @@ const extract = doc => {
|
|||||||
logger.info(doc);
|
logger.info(doc);
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
logger.info('Extract', doc);
|
||||||
|
|
||||||
doc.forEach(item => {
|
doc.forEach(item => {
|
||||||
if (item.stmt === 'state') {
|
if (item.stmt === 'state') {
|
||||||
addState(item.id, item.type, item.doc, item.description, item.note);
|
addState(item.id, item.type, item.doc, item.description, item.note);
|
||||||
|
@@ -72,10 +72,8 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const nodeData = {
|
const nodeData = {
|
||||||
labelType: 'svg',
|
|
||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
shape: nodeDb[node.id].shape,
|
shape: nodeDb[node.id].shape,
|
||||||
label: node.id,
|
|
||||||
labelText: nodeDb[node.id].description,
|
labelText: nodeDb[node.id].description,
|
||||||
classes: nodeDb[node.id].classes, //classStr,
|
classes: nodeDb[node.id].classes, //classStr,
|
||||||
style: '', //styles.style,
|
style: '', //styles.style,
|
||||||
@@ -87,10 +85,8 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
if (node.note) {
|
if (node.note) {
|
||||||
// Todo: set random id
|
// Todo: set random id
|
||||||
const noteData = {
|
const noteData = {
|
||||||
labelType: 'svg',
|
|
||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
shape: 'note',
|
shape: 'note',
|
||||||
label: node.id,
|
|
||||||
labelText: node.note.text,
|
labelText: node.note.text,
|
||||||
classes: 'statediagram-note', //classStr,
|
classes: 'statediagram-note', //classStr,
|
||||||
style: '', //styles.style,
|
style: '', //styles.style,
|
||||||
@@ -99,10 +95,8 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
padding: 15 //getConfig().flowchart.padding
|
padding: 15 //getConfig().flowchart.padding
|
||||||
};
|
};
|
||||||
const groupData = {
|
const groupData = {
|
||||||
labelType: 'svg',
|
|
||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
shape: 'noteGroup',
|
shape: 'noteGroup',
|
||||||
label: node.id + '----parent',
|
|
||||||
labelText: node.note.text,
|
labelText: node.note.text,
|
||||||
classes: nodeDb[node.id].classes, //classStr,
|
classes: nodeDb[node.id].classes, //classStr,
|
||||||
style: '', //styles.style,
|
style: '', //styles.style,
|
||||||
@@ -133,8 +127,7 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
classes: 'note-edge',
|
classes: 'note-edge',
|
||||||
arrowheadStyle: 'fill: #333',
|
arrowheadStyle: 'fill: #333',
|
||||||
labelpos: 'c',
|
labelpos: 'c',
|
||||||
labelType: 'text',
|
labelType: 'text'
|
||||||
label: ''
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
g.setNode(node.id, nodeData);
|
g.setNode(node.id, nodeData);
|
||||||
@@ -143,12 +136,12 @@ const setupNode = (g, parent, node, altFlag) => {
|
|||||||
|
|
||||||
if (parent) {
|
if (parent) {
|
||||||
if (parent.id !== 'root') {
|
if (parent.id !== 'root') {
|
||||||
logger.trace('Setting node ', node.id, ' to be child of its parent ', parent.id);
|
logger.info('Setting node ', node.id, ' to be child of its parent ', parent.id);
|
||||||
g.setParent(node.id, parent.id);
|
g.setParent(node.id, parent.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node.doc) {
|
if (node.doc) {
|
||||||
logger.trace('Adding nodes children ');
|
logger.info('Adding nodes children ');
|
||||||
setupDoc(g, node, node.doc, !altFlag);
|
setupDoc(g, node, node.doc, !altFlag);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -168,8 +161,7 @@ const setupDoc = (g, parent, doc, altFlag) => {
|
|||||||
labelStyle: '',
|
labelStyle: '',
|
||||||
arrowheadStyle: 'fill: #333',
|
arrowheadStyle: 'fill: #333',
|
||||||
labelpos: 'c',
|
labelpos: 'c',
|
||||||
labelType: 'text',
|
labelType: 'text'
|
||||||
label: ''
|
|
||||||
};
|
};
|
||||||
let startId = item.state1.id;
|
let startId = item.state1.id;
|
||||||
let endId = item.state2.id;
|
let endId = item.state2.id;
|
||||||
@@ -214,7 +206,7 @@ export const draw = function(text, id) {
|
|||||||
compound: true
|
compound: true
|
||||||
})
|
})
|
||||||
.setGraph({
|
.setGraph({
|
||||||
rankdir: 'LR',
|
rankdir: 'TB',
|
||||||
nodesep: nodeSpacing,
|
nodesep: nodeSpacing,
|
||||||
ranksep: rankSpacing,
|
ranksep: rankSpacing,
|
||||||
marginx: 8,
|
marginx: 8,
|
||||||
@@ -224,8 +216,8 @@ export const draw = function(text, id) {
|
|||||||
return {};
|
return {};
|
||||||
});
|
});
|
||||||
|
|
||||||
// logger.info(stateDb.getRootDoc());
|
logger.info(stateDb.getRootDocV2());
|
||||||
stateDb.extract(stateDb.getRootDocV2().doc);
|
stateDb.extract(stateDb.getRootDocV2());
|
||||||
logger.info(stateDb.getRootDocV2());
|
logger.info(stateDb.getRootDocV2());
|
||||||
setupNode(g, undefined, stateDb.getRootDocV2(), true);
|
setupNode(g, undefined, stateDb.getRootDocV2(), true);
|
||||||
|
|
||||||
|
16
src/utils.js
16
src/utils.js
@@ -210,6 +210,19 @@ export const getStylesFromArray = arr => {
|
|||||||
return { style: style, labelStyle: labelStyle };
|
return { style: style, labelStyle: labelStyle };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let cnt = 0;
|
||||||
|
export const generateId = () => {
|
||||||
|
cnt++;
|
||||||
|
return (
|
||||||
|
'id-' +
|
||||||
|
Math.random()
|
||||||
|
.toString(36)
|
||||||
|
.substr(2, 12) +
|
||||||
|
'-' +
|
||||||
|
cnt
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
detectType,
|
detectType,
|
||||||
isSubstringInArray,
|
isSubstringInArray,
|
||||||
@@ -217,5 +230,6 @@ export default {
|
|||||||
calcLabelPosition,
|
calcLabelPosition,
|
||||||
calcCardinalityPosition,
|
calcCardinalityPosition,
|
||||||
formatUrl,
|
formatUrl,
|
||||||
getStylesFromArray
|
getStylesFromArray,
|
||||||
|
generateId
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user