#1295 Adding support for multiline descriptions for states

This commit is contained in:
Knut Sveidqvist 2020-04-25 17:01:20 +02:00
parent e52d4ce033
commit 0aede618ec
5 changed files with 97 additions and 16 deletions

View File

@ -49,20 +49,10 @@
}
</div>
<div class="mermaid" 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
}
stateDiagram-v2
[*] --> S1
state "Some long name" as S1: The description<br/>continues
</div>
<div class="mermaid2 mermaid-apa" style="width: 100%; height: 20%;">
stateDiagram

View File

@ -1,4 +1,4 @@
const createLabel = (vertexText, style) => {
const createLabel = (vertexText, style, isTitle) => {
const svgLabel = document.createElementNS('http://www.w3.org/2000/svg', 'text');
svgLabel.setAttribute('style', style.replace('color:', 'fill:'));
let rows = [];
@ -11,6 +11,11 @@ const createLabel = (vertexText, style) => {
tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
tspan.setAttribute('dy', '1em');
tspan.setAttribute('x', '0');
if (isTitle) {
tspan.setAttribute('class', 'title-row');
} else {
tspan.setAttribute('class', 'row');
}
tspan.textContent = rows[j].trim();
svgLabel.appendChild(tspan);
}

View File

@ -1,6 +1,8 @@
import intersect from './intersect/index.js';
import { select } from 'd3';
import { logger } from '../logger'; // eslint-disable-line
import { labelHelper, updateNodeBounds, insertPolygonShape } from './shapes/util';
import createLabel from './createLabel';
import note from './shapes/note';
const question = (parent, node) => {
@ -269,6 +271,76 @@ const rect = (parent, node) => {
return shapeSvg;
};
const rectWithTitle = (parent, node) => {
// const { shapeSvg, bbox, halfPadding } = labelHelper(parent, node, 'node ' + node.classes);
let classes;
if (!node.classes) {
classes = 'node default';
} else {
classes = 'node ' + node.classes;
}
// Add outer g element
const shapeSvg = parent
.insert('g')
.attr('class', classes)
.attr('id', node.id);
// Create the title label and insert it after the rect
const rect = shapeSvg.insert('rect', ':first-child');
// const innerRect = shapeSvg.insert('rect');
const innerLine = shapeSvg.insert('line');
const label = shapeSvg.insert('g').attr('class', 'label');
const text = label.node().appendChild(createLabel(node.labelText[0], node.labelStyle, true));
const textRows = node.labelText.slice(1, node.labelText.length);
let titleBox = text.getBBox();
const descr = label
.node()
.appendChild(createLabel(textRows.join('<br/>'), node.labelStyle, true));
logger.info(descr);
const halfPadding = node.padding / 2;
select(descr).attr('transform', 'translate( 0' + ', ' + (titleBox.height + halfPadding) + ')');
// Get the size of the label
// Bounding box for title and text
const bbox = label.node().getBBox();
// Center the label
label.attr(
'transform',
'translate(' + -bbox.width / 2 + ', ' + (-bbox.height / 2 - halfPadding + 3) + ')'
);
rect
.attr('class', 'outer title-state')
.attr('x', -bbox.width / 2 - halfPadding)
.attr('y', -bbox.height / 2 - halfPadding)
.attr('width', bbox.width + node.padding)
.attr('height', bbox.height + node.padding);
// innerRect
// .attr('class', 'inner')
// .attr('x', -bbox.width / 2 - halfPadding)
// .attr('y', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding)
// .attr('width', bbox.width + node.padding)
// .attr('height', bbox.height + node.padding - titleBox.height - halfPadding);
innerLine
.attr('class', 'divider')
.attr('x1', -bbox.width / 2 - halfPadding)
.attr('x2', bbox.width / 2 + halfPadding)
.attr('y1', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding)
.attr('y2', -bbox.height / 2 - halfPadding + titleBox.height + halfPadding);
updateNodeBounds(node, rect);
node.intersect = function(point) {
return intersect.rect(node, point);
};
return shapeSvg;
};
const stadium = (parent, node) => {
const { shapeSvg, bbox } = labelHelper(parent, node);
@ -368,6 +440,7 @@ const end = (parent, node) => {
const shapes = {
question,
rect,
rectWithTitle,
circle,
stadium,
hexagon,

View File

@ -54,7 +54,12 @@ const setupNode = (g, parent, node, altFlag) => {
// Description
if (node.description) {
nodeDb[node.id].description = node.description;
if (Array.isArray(node.description)) {
nodeDb[node.id].shape = 'rectWithTitle';
nodeDb[node.id].description = node.description;
} else {
nodeDb[node.id].description = node.description;
}
}
// Save data for description and group so that for instance a statement without description overwrites

View File

@ -90,6 +90,14 @@ g.stateGroup line {
rx: 5px;
ry: 5px;
}
.statediagram-state .divider {
stroke: $nodeBorder;
}
.statediagram-state .title-state {
rx: 5px;
ry: 5px;
}
.statediagram-cluster.statediagram-cluster .inner {
fill: white;
}