diff --git a/cypress/platform/current.html b/cypress/platform/current.html index 01ce04d88..c5c1d2486 100644 --- a/cypress/platform/current.html +++ b/cypress/platform/current.html @@ -18,6 +18,14 @@

info below

+
+ flowchart LR + a --> b + + subgraph b [Test] + c --> d -->e + end +
flowchart LR a --> b @@ -40,7 +48,7 @@ Eating }
-
+
stateDiagram-v2 state Active { [*] --> NumLockOff @@ -73,8 +81,8 @@
stateDiagram-v2 [*] --> First - First --> Second -% First --> Third + First --> Third + First --> sec state First { [*] --> fir @@ -83,9 +91,14 @@ stateDiagram-v2 state Second { [*] --> sec sec --> [*] - } + } + state Third { + [*] --> thi + thi --> [*] + } + thi --> sec
-
+
flowchart TD subgraph A a @@ -101,7 +114,7 @@ flowchart TD A -- oAo --o B A --> C
-
+
flowchart TD subgraph A a @@ -133,28 +146,27 @@ stateDiagram-v2
stateDiagram-v2 - [*]-->TV + [*]-->TV - state TV { - [*] --> Off: Off to start with - On --> Off : Turn off - Off --> On : Turn on - } + state TV { + [*] --> Off: Off to start with + On --> Off : Turn off + Off --> On : Turn on + } - TV--> Console + TV--> Console - state Console { - [*] --> Off2: Off to start with - On2--> Off2 : Turn off - Off2 --> On2 : Turn on - On2-->Playing - - state Playing { - Alive --> Dead - Dead-->Alive - } - } + state Console { + [*] --> Off2: Off to start with + On2--> Off2 : Turn off + Off2 --> On2 : Turn on + On2-->Playing + state Playing { + Alive --> Dead + Dead-->Alive + } + }
diff --git a/src/dagre-wrapper/clusters.js b/src/dagre-wrapper/clusters.js index ac1163be8..a1f76477e 100644 --- a/src/dagre-wrapper/clusters.js +++ b/src/dagre-wrapper/clusters.js @@ -149,7 +149,64 @@ const roundedWithTitle = (parent, node) => { return shapeSvg; }; -const shapes = { rect, roundedWithTitle, noteGroup }; +const divider = (parent, node) => { + // Add outer g element + const shapeSvg = parent + .insert('g') + .attr('class', node.classes) + .attr('id', node.id); + + // add the rect + const rect = shapeSvg.insert('rect', ':first-child'); + + // Create the label and insert it after the rect + const label = shapeSvg.insert('g').attr('class', 'cluster-label'); + const innerRect = shapeSvg.append('rect'); + + const text = label.node().appendChild(createLabel(node.labelText, node.labelStyle)); + + // Get the size of the label + const bbox = text.getBBox(); + + const padding = 0 * node.padding; + const halfPadding = padding / 2; + + // center the rect around its coordinate + rect + .attr('class', 'divider') + .attr('x', node.x - node.width / 2 - halfPadding) + .attr('y', node.y - node.height / 2 - halfPadding) + .attr('width', node.width + padding) + .attr('height', node.height + padding); + // innerRect + // .attr('class', 'inner') + // .attr('x', node.x - node.width / 2 - halfPadding) + // .attr('y', node.y - node.height / 2 - halfPadding + bbox.height - 1) + // .attr('width', node.width + padding) + // .attr('height', node.height + padding - bbox.height); + + // Center the label + label.attr( + 'transform', + 'translate(' + + (node.x - bbox.width / 2) + + ', ' + + (node.y - node.height / 2 - node.padding / 3 + 3) + + ')' + ); + + const rectBox = rect.node().getBBox(); + node.width = rectBox.width; + node.height = rectBox.height; + + node.intersect = function(point) { + return intersectRect(node, point); + }; + + return shapeSvg; +}; + +const shapes = { rect, roundedWithTitle, noteGroup, divider }; let clusterElems = {}; diff --git a/src/dagre-wrapper/index.js b/src/dagre-wrapper/index.js index dca32ddc8..5d33e9a2e 100644 --- a/src/dagre-wrapper/index.js +++ b/src/dagre-wrapper/index.js @@ -14,7 +14,7 @@ import { insertEdgeLabel, positionEdgeLabel, insertEdge, clear as clearEdges } f import { logger as log } from '../logger'; const recursiveRender = (_elem, graph, diagramtype, parentCluster) => { - log.trace('Graph in recursive render:', graphlib.json.write(graph), parentCluster); + log.info('Graph in recursive render:', graphlib.json.write(graph), parentCluster); const elem = _elem.insert('g').attr('class', 'root'); // eslint-disable-line if (!graph.nodes()) { log.trace('No nodes found for', graph); diff --git a/src/dagre-wrapper/mermaid-graphlib.js b/src/dagre-wrapper/mermaid-graphlib.js index 9b8e61fdd..786af7b46 100644 --- a/src/dagre-wrapper/mermaid-graphlib.js +++ b/src/dagre-wrapper/mermaid-graphlib.js @@ -31,13 +31,17 @@ const isDecendant = (id, ancenstorId) => { }; const edgeInCluster = (edge, clusterId) => { + log.info('Decendants of ', clusterId, ' is ', decendants[clusterId]); + log.info('Edge is ', edge); // Edges to/from the cluster is not in the cluster, they are in the parent - if (!(edge.v === clusterId || edge.w === clusterId)) return false; + if (edge.v === clusterId) return false; + if (edge.w === clusterId) return false; if (!decendants[clusterId]) { log.debug('Tilt, ', clusterId, ',not in decendants'); return false; } + log.info('Here '); if (decendants[clusterId].indexOf(edge.v) >= 0) return true; if (isDecendant(edge.v, clusterId)) return true; @@ -80,17 +84,26 @@ const copy = (clusterId, graph, newGraph, rootId) => { const edges = graph.edges(node); log.debug('Copying Edges', edges); edges.forEach(edge => { - log.trace('Edge', edge); + log.info('Edge', edge); const data = graph.edge(edge.v, edge.w, edge.name); - log.trace('Edge data', data, rootId); + log.info('Edge data', data, rootId); try { // Do not copy edges in and out of the root cluster, they belong to the parent graph if (edgeInCluster(edge, rootId)) { - log.trace('Copying as ', edge.v, edge.w, data, edge.name); + log.info('Copying as ', edge.v, edge.w, data, edge.name); newGraph.setEdge(edge.v, edge.w, data, edge.name); - log.trace('newGraph edges ', newGraph.edges(), newGraph.edge(newGraph.edges()[0])); + log.info('newGraph edges ', newGraph.edges(), newGraph.edge(newGraph.edges()[0])); } else { - log.trace('Skipping copy of edge as ', rootId, edge.v, edge.w, clusterId); + log.info( + 'Skipping copy of edge ', + edge.v, + '-->', + edge.w, + ' rootId: ', + rootId, + ' clusterId:', + clusterId + ); } } catch (e) { log.error(e); diff --git a/src/dagre-wrapper/mermaid-graphlib.spec.js b/src/dagre-wrapper/mermaid-graphlib.spec.js index 33fea60de..73bc9a5a7 100644 --- a/src/dagre-wrapper/mermaid-graphlib.spec.js +++ b/src/dagre-wrapper/mermaid-graphlib.spec.js @@ -314,6 +314,34 @@ describe('Graphlib decorations', () => { // expect(edgeData.data).toBe('link2'); // expect(validate(g)).toBe(true); }); + it('adjustClustersAndEdges the extracted graphs shall contain the correct links GLB20', function () { + /* + a --> b + subgraph b [Test] + c --> d -->e + end + */ + g.setNode('a', { data: 1 }); + g.setNode('b', { data: 2 }); + g.setNode('c', { data: 3 }); + g.setNode('d', { data: 3 }); + g.setNode('e', { data: 3 }); + g.setParent('c', 'b'); + g.setParent('d', 'b'); + g.setParent('e', 'b'); + g.setEdge('a', 'b', { data: 'link1' }, '1'); + g.setEdge('c', 'd', { data: 'link2' }, '2'); + g.setEdge('d', 'e', { data: 'link2' }, '2'); + + logger.info('Graph before', graphlib.json.write(g)) + adjustClustersAndEdges(g); + const bGraph = g.node('b').graph; + // logger.trace('Graph after', graphlib.json.write(g)) + logger.info('Graph after', graphlib.json.write(bGraph)); + expect(bGraph.nodes().length).toBe(3); + expect(bGraph.edges().length).toBe(2); + }); + }); }); describe('extractDecendants', function () { diff --git a/src/dagre-wrapper/nodes.js b/src/dagre-wrapper/nodes.js index 08a0e36db..809f09701 100644 --- a/src/dagre-wrapper/nodes.js +++ b/src/dagre-wrapper/nodes.js @@ -253,6 +253,7 @@ const rect = (parent, node) => { const rect = shapeSvg.insert('rect', ':first-child'); rect + .attr('class', 'basic') .attr('rx', node.rx) .attr('ry', node.ry) .attr('x', -bbox.width / 2 - halfPadding) diff --git a/src/dagre-wrapper/patterns.js b/src/dagre-wrapper/patterns.js new file mode 100644 index 000000000..f607433d7 --- /dev/null +++ b/src/dagre-wrapper/patterns.js @@ -0,0 +1,54 @@ +/** + * Setup arrow head and define the marker. The result is appended to the svg. + */ + +import { logger } from '../logger'; + +// Only add the number of markers that the diagram needs +const insertPatterns = (elem, patternArray, type, id) => { + patternArray.forEach(patternName => { + patterns[patternName](elem, type, id); + }); +}; + +{ + /* + {' '} + + {' '} + + {' '} + + {' '} + {' '} + {' '} + {' '} +; */ +} + +const dots = (elem, type) => { + elem + .append('defs') + .append('marker') + .attr('id', type + '-barbEnd') + .attr('refX', 19) + .attr('refY', 7) + .attr('markerWidth', 20) + .attr('markerHeight', 14) + .attr('markerUnits', 0) + .attr('orient', 'auto') + .append('path') + .attr('d', 'M 19,7 L9,13 L14,7 L9,1 Z'); +}; + +// TODO rename the class diagram markers to something shape descriptive and semanitc free +const patterns = { + dots +}; +export default insertPatterns; diff --git a/src/diagrams/state/stateRenderer-v2.js b/src/diagrams/state/stateRenderer-v2.js index f69d94ed3..5952f96dc 100644 --- a/src/diagrams/state/stateRenderer-v2.js +++ b/src/diagrams/state/stateRenderer-v2.js @@ -64,7 +64,7 @@ const setupNode = (g, parent, node, altFlag) => { if (!nodeDb[node.id].type && node.doc) { logger.info('Setting cluser for ', node.id); nodeDb[node.id].type = 'group'; - nodeDb[node.id].shape = 'roundedWithTitle'; + nodeDb[node.id].shape = node.type === 'divider' ? 'divider' : 'roundedWithTitle'; nodeDb[node.id].classes = nodeDb[node.id].classes + ' ' + diff --git a/src/themes/state.scss b/src/themes/state.scss index aa8bd4df3..6055db2d9 100644 --- a/src/themes/state.scss +++ b/src/themes/state.scss @@ -85,6 +85,8 @@ g.stateGroup line { fill: $nodeBkg; stroke: $nodeBorder; stroke-width: 1px; +} +.statediagram-cluster rect.outer { rx: 5px; ry: 5px; } @@ -100,10 +102,14 @@ g.stateGroup line { ry:0; } -.statediagram-state rect { +.statediagram-state rect.basic { rx: 5px; ry: 5px; } +.statediagram-state rect.divider { + stroke-dasharray: 10,10; + fill: #efefef; +} .note-edge { stroke-dasharray: 5;