From ce0b0fa0c8e654ce833df52676f1fe157b9d2de4 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Sun, 6 Oct 2019 15:44:31 +0200 Subject: [PATCH] #945 Divider lines for concurrency --- .../rendering/stateDiagram.spec.js | 24 +++++++++++++++++++ src/diagrams/state/parser/stateDiagram.jison | 4 +++- src/diagrams/state/shapes.js | 15 ++++++++++++ src/diagrams/state/stateDb.js | 7 ++++++ src/diagrams/state/stateRenderer.js | 18 ++++++++++++++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/cypress/integration/rendering/stateDiagram.spec.js b/cypress/integration/rendering/stateDiagram.spec.js index c7f214be3..bf2055008 100644 --- a/cypress/integration/rendering/stateDiagram.spec.js +++ b/cypress/integration/rendering/stateDiagram.spec.js @@ -181,4 +181,28 @@ describe('State diagram', () => { ); cy.get('svg'); }); + it('should render conurrency states', () => { + imgSnapshotTest( + ` + stateDiagram + [*] --> Active + + state Active { + [*] --> NumLockOff + NumLockOff --> NumLockOn : EvNumLockPressed + NumLockOn --> NumLockOff : EvNumLockPressed + -- + [*] --> CapsLockOff + CapsLockOff --> CapsLockOn : EvCapsLockPressed + CapsLockOn --> CapsLockOff : EvCapsLockPressed + -- + [*] --> ScrollLockOff + ScrollLockOff --> ScrollLockOn : EvCapsLockPressed + ScrollLockOn --> ScrollLockOff : EvCapsLockPressed + } + `, + { logLevel: 0 } + ); + cy.get('svg'); + }); }); diff --git a/src/diagrams/state/parser/stateDiagram.jison b/src/diagrams/state/parser/stateDiagram.jison index e79c8c4f1..000f26b4b 100644 --- a/src/diagrams/state/parser/stateDiagram.jison +++ b/src/diagrams/state/parser/stateDiagram.jison @@ -143,7 +143,9 @@ statement | JOIN { $$={ stmt: 'state', id: $1, type: 'join' } } - | CONCURRENT + | CONCURRENT { + $$={ stmt: 'state', id: yy.getDividerId(), type: 'divider' } + } | note notePosition ID NOTE_TEXT { console.warn('got NOTE, position: ', $2.trim(), 'id = ', $3.trim(), 'note: ', $4); diff --git a/src/diagrams/state/shapes.js b/src/diagrams/state/shapes.js index f1d19ac18..dc3754de8 100644 --- a/src/diagrams/state/shapes.js +++ b/src/diagrams/state/shapes.js @@ -25,6 +25,20 @@ export const drawStartState = g => .attr('cx', conf.padding + 5) .attr('cy', conf.padding + 5); +/** + * Draws a start state as a black circle + */ +export const drawDivider = g => + g + .append('line') + .style('stroke', 'grey') + .style('stroke-dasharray', '3') + .attr('x1', 10) + .attr('class', 'divider') + .attr('x2', 20) + .attr('y1', 20) + .attr('y2', 20); + /** * Draws a an end state as a black circle */ @@ -276,6 +290,7 @@ export const drawState = function(elem, stateDef, graph, doc) { if (stateDef.type === 'end') drawEndState(g); if (stateDef.type === 'fork' || stateDef.type === 'join') drawForkJoinState(g); if (stateDef.type === 'note') drawNote(stateDef.note.text, g); + if (stateDef.type === 'divider') drawDivider(g); if (stateDef.type === 'default' && stateDef.descriptions.length === 0) drawSimpleState(g, stateDef); if (stateDef.type === 'default' && stateDef.descriptions.length > 0) drawDescrState(g, stateDef); diff --git a/src/diagrams/state/stateDb.js b/src/diagrams/state/stateDb.js index 9a5ed487b..c2749087a 100644 --- a/src/diagrams/state/stateDb.js +++ b/src/diagrams/state/stateDb.js @@ -133,6 +133,12 @@ export const lineType = { DOTTED_LINE: 1 }; +let dividerCnt = 0; +const getDividerId = () => { + dividerCnt++; + return 'divider-id-' + dividerCnt; +}; + export const relationType = { AGGREGATION: 0, EXTENSION: 1, @@ -147,6 +153,7 @@ export default { getStates, getRelations, addRelation, + getDividerId, // addDescription, cleanupLabel, lineType, diff --git a/src/diagrams/state/stateRenderer.js b/src/diagrams/state/stateRenderer.js index 34a28cf4b..23fa0c778 100644 --- a/src/diagrams/state/stateRenderer.js +++ b/src/diagrams/state/stateRenderer.js @@ -224,10 +224,28 @@ const renderDoc = (doc, diagram, parentId) => { graph.node(v).height / 2) + ' )' ); + d3.select('#' + v).attr('data-x-shift', graph.node(v).x - graph.node(v).width / 2); + const dividers = document.querySelectorAll('#' + v + ' .divider'); + dividers.forEach(divider => { + const parent = divider.parentElement; + let pWidth = 0; + let pShift = 0; + if (parent) { + if (parent.parentElement) pWidth = parent.parentElement.getBBox().width; + + pShift = parseInt(parent.getAttribute('data-x-shift'), 10); + if (Number.isNaN(pShift)) { + pShift = 0; + } + } + divider.setAttribute('x1', 0 - pShift); + divider.setAttribute('x2', pWidth - pShift); + }); } else { console.warn('No Node ' + v + ': ' + JSON.stringify(graph.node(v))); } }); + let stateBox = diagram.node().getBBox(); console.warn('Node before labels ', stateBox.width);