mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-04 16:16:41 +02:00
Allow overlapping notes
This commit is contained in:
@@ -59,6 +59,7 @@
|
|||||||
"knsv",
|
"knsv",
|
||||||
"knut",
|
"knut",
|
||||||
"laganeckas",
|
"laganeckas",
|
||||||
|
"linetype",
|
||||||
"lintstagedrc",
|
"lintstagedrc",
|
||||||
"logmsg",
|
"logmsg",
|
||||||
"lucida",
|
"lucida",
|
||||||
|
@@ -123,6 +123,29 @@ context('Sequence diagram', () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
it('should render a sequence diagram with par_over', () => {
|
||||||
|
imgSnapshotTest(
|
||||||
|
`
|
||||||
|
sequenceDiagram
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
participant John
|
||||||
|
par_over Section title
|
||||||
|
Alice ->> Bob: Message 1<br>Second line
|
||||||
|
Bob ->> John: Message 2
|
||||||
|
end
|
||||||
|
par_over Two line<br>section title
|
||||||
|
Note over Alice: Alice note
|
||||||
|
Note over Bob: Bob note<br>Second line
|
||||||
|
Note over John: John note
|
||||||
|
end
|
||||||
|
par_over Mixed section
|
||||||
|
Alice ->> Bob: Message 1
|
||||||
|
Note left of Bob: Alice/Bob Note
|
||||||
|
end
|
||||||
|
`
|
||||||
|
);
|
||||||
|
});
|
||||||
context('font settings', () => {
|
context('font settings', () => {
|
||||||
it('should render different note fonts when configured', () => {
|
it('should render different note fonts when configured', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
|
@@ -144,6 +144,26 @@
|
|||||||
>
|
>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
participant John
|
||||||
|
par_over Section title
|
||||||
|
Alice ->> Bob: Message 1<br>Second line
|
||||||
|
Bob ->> John: Message 2
|
||||||
|
end
|
||||||
|
par_over Two line<br>section title
|
||||||
|
Note over Alice: Alice note
|
||||||
|
Note over Bob: Bob note<br>Second line
|
||||||
|
Note over John: John note
|
||||||
|
end
|
||||||
|
par_over Mixed section
|
||||||
|
Alice ->> Bob: Message 1
|
||||||
|
Note left of Bob: Alice/Bob Note
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
@@ -138,6 +138,32 @@ const getUrl = (useAbsolute: boolean): string => {
|
|||||||
export const evaluate = (val?: string | boolean): boolean =>
|
export const evaluate = (val?: string | boolean): boolean =>
|
||||||
val === false || ['false', 'null', '0'].includes(String(val).trim().toLowerCase()) ? false : true;
|
val === false || ['false', 'null', '0'].includes(String(val).trim().toLowerCase()) ? false : true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around Math.max which removes non-numeric values
|
||||||
|
* Returns the larger of a set of supplied numeric expressions.
|
||||||
|
* @param values - Numeric expressions to be evaluated
|
||||||
|
* @returns The smaller value
|
||||||
|
*/
|
||||||
|
export const getMax = function (...values: number[]): number {
|
||||||
|
const newValues: number[] = values.filter((value) => {
|
||||||
|
return !isNaN(value);
|
||||||
|
});
|
||||||
|
return Math.max(...newValues);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around Math.min which removes non-numeric values
|
||||||
|
* Returns the smaller of a set of supplied numeric expressions.
|
||||||
|
* @param values - Numeric expressions to be evaluated
|
||||||
|
* @returns The smaller value
|
||||||
|
*/
|
||||||
|
export const getMin = function (...values: number[]): number {
|
||||||
|
const newValues: number[] = values.filter((value) => {
|
||||||
|
return !isNaN(value);
|
||||||
|
});
|
||||||
|
return Math.min(...newValues);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes generics in typescript syntax
|
* Makes generics in typescript syntax
|
||||||
*
|
*
|
||||||
@@ -180,4 +206,6 @@ export default {
|
|||||||
removeScript,
|
removeScript,
|
||||||
getUrl,
|
getUrl,
|
||||||
evaluate,
|
evaluate,
|
||||||
|
getMax,
|
||||||
|
getMin,
|
||||||
};
|
};
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
"alt" { this.begin('LINE'); return 'alt'; }
|
"alt" { this.begin('LINE'); return 'alt'; }
|
||||||
"else" { this.begin('LINE'); return 'else'; }
|
"else" { this.begin('LINE'); return 'else'; }
|
||||||
"par" { this.begin('LINE'); return 'par'; }
|
"par" { this.begin('LINE'); return 'par'; }
|
||||||
|
"par_over" { this.begin('LINE'); return 'par_over'; }
|
||||||
"and" { this.begin('LINE'); return 'and'; }
|
"and" { this.begin('LINE'); return 'and'; }
|
||||||
"critical" { this.begin('LINE'); return 'critical'; }
|
"critical" { this.begin('LINE'); return 'critical'; }
|
||||||
"option" { this.begin('LINE'); return 'option'; }
|
"option" { this.begin('LINE'); return 'option'; }
|
||||||
@@ -190,6 +191,14 @@ statement
|
|||||||
// End
|
// End
|
||||||
$3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END});
|
$3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END});
|
||||||
$$=$3;}
|
$$=$3;}
|
||||||
|
| par_over restOfLine par_sections end
|
||||||
|
{
|
||||||
|
// Parallel (overlapped) start
|
||||||
|
$3.unshift({type: 'parStart', parText:yy.parseMessage($2), signalType: yy.LINETYPE.PAR_OVER_START});
|
||||||
|
// Content in par is already in $3
|
||||||
|
// End
|
||||||
|
$3.push({type: 'parEnd', signalType: yy.LINETYPE.PAR_END});
|
||||||
|
$$=$3;}
|
||||||
| critical restOfLine option_sections end
|
| critical restOfLine option_sections end
|
||||||
{
|
{
|
||||||
// critical start
|
// critical start
|
||||||
|
@@ -286,6 +286,7 @@ export const LINETYPE = {
|
|||||||
CRITICAL_END: 29,
|
CRITICAL_END: 29,
|
||||||
BREAK_START: 30,
|
BREAK_START: 30,
|
||||||
BREAK_END: 31,
|
BREAK_END: 31,
|
||||||
|
PAR_OVER_START: 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ARROWTYPE = {
|
export const ARROWTYPE = {
|
||||||
|
@@ -1126,6 +1126,29 @@ end`;
|
|||||||
expect(messages[1].from).toBe('Alice');
|
expect(messages[1].from).toBe('Alice');
|
||||||
expect(messages[2].from).toBe('Bob');
|
expect(messages[2].from).toBe('Bob');
|
||||||
});
|
});
|
||||||
|
it('it should handle par_over statements', async () => {
|
||||||
|
const str = `
|
||||||
|
sequenceDiagram
|
||||||
|
par_over Parallel overlap
|
||||||
|
Alice ->> Bob: Message
|
||||||
|
Note left of Alice: Alice note
|
||||||
|
Note right of Bob: Bob note
|
||||||
|
end`;
|
||||||
|
|
||||||
|
await mermaidAPI.parse(str);
|
||||||
|
const actors = diagram.db.getActors();
|
||||||
|
|
||||||
|
expect(actors.Alice.description).toBe('Alice');
|
||||||
|
expect(actors.Bob.description).toBe('Bob');
|
||||||
|
|
||||||
|
const messages = diagram.db.getMessages();
|
||||||
|
|
||||||
|
expect(messages.length).toBe(5);
|
||||||
|
expect(messages[0].message).toBe('Parallel overlap');
|
||||||
|
expect(messages[1].from).toBe('Alice');
|
||||||
|
expect(messages[2].from).toBe('Alice');
|
||||||
|
expect(messages[3].from).toBe('Bob');
|
||||||
|
});
|
||||||
it('should handle special characters in signals', async () => {
|
it('should handle special characters in signals', async () => {
|
||||||
const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment';
|
const str = 'sequenceDiagram\n' + 'Alice->Bob: -:<>,;# comment';
|
||||||
|
|
||||||
|
@@ -131,10 +131,10 @@ export const bounds = {
|
|||||||
this.activations.forEach(updateFn('activation'));
|
this.activations.forEach(updateFn('activation'));
|
||||||
},
|
},
|
||||||
insert: function (startx, starty, stopx, stopy) {
|
insert: function (startx, starty, stopx, stopy) {
|
||||||
const _startx = Math.min(startx, stopx);
|
const _startx = common.getMin(startx, stopx);
|
||||||
const _stopx = Math.max(startx, stopx);
|
const _stopx = common.getMax(startx, stopx);
|
||||||
const _starty = Math.min(starty, stopy);
|
const _starty = common.getMin(starty, stopy);
|
||||||
const _stopy = Math.max(starty, stopy);
|
const _stopy = common.getMax(starty, stopy);
|
||||||
|
|
||||||
this.updateVal(bounds.data, 'startx', _startx, Math.min);
|
this.updateVal(bounds.data, 'startx', _startx, Math.min);
|
||||||
this.updateVal(bounds.data, 'starty', _starty, Math.min);
|
this.updateVal(bounds.data, 'starty', _starty, Math.min);
|
||||||
@@ -184,6 +184,11 @@ export const bounds = {
|
|||||||
endLoop: function () {
|
endLoop: function () {
|
||||||
return this.sequenceItems.pop();
|
return this.sequenceItems.pop();
|
||||||
},
|
},
|
||||||
|
isLoopOverlap: function () {
|
||||||
|
return this.sequenceItems.length
|
||||||
|
? this.sequenceItems[this.sequenceItems.length - 1].overlap
|
||||||
|
: false;
|
||||||
|
},
|
||||||
addSectionToLoop: function (message) {
|
addSectionToLoop: function (message) {
|
||||||
const loop = this.sequenceItems.pop();
|
const loop = this.sequenceItems.pop();
|
||||||
loop.sections = loop.sections || [];
|
loop.sections = loop.sections || [];
|
||||||
@@ -192,9 +197,19 @@ export const bounds = {
|
|||||||
loop.sectionTitles.push(message);
|
loop.sectionTitles.push(message);
|
||||||
this.sequenceItems.push(loop);
|
this.sequenceItems.push(loop);
|
||||||
},
|
},
|
||||||
|
saveVerticalPos: function () {
|
||||||
|
if (this.isLoopOverlap()) {
|
||||||
|
this.savedVerticalPos = this.verticalPos;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resetVerticalPos: function () {
|
||||||
|
if (this.isLoopOverlap()) {
|
||||||
|
this.verticalPos = this.savedVerticalPos;
|
||||||
|
}
|
||||||
|
},
|
||||||
bumpVerticalPos: function (bump) {
|
bumpVerticalPos: function (bump) {
|
||||||
this.verticalPos = this.verticalPos + bump;
|
this.verticalPos = this.verticalPos + bump;
|
||||||
this.data.stopy = this.verticalPos;
|
this.data.stopy = common.getMax(this.data.stopy, this.verticalPos);
|
||||||
},
|
},
|
||||||
getVerticalPos: function () {
|
getVerticalPos: function () {
|
||||||
return this.verticalPos;
|
return this.verticalPos;
|
||||||
@@ -317,7 +332,7 @@ function boundMessage(_diagram, msgModel): number {
|
|||||||
lineStartY = bounds.getVerticalPos() + totalOffset;
|
lineStartY = bounds.getVerticalPos() + totalOffset;
|
||||||
}
|
}
|
||||||
totalOffset += 30;
|
totalOffset += 30;
|
||||||
const dx = Math.max(textWidth / 2, conf.width / 2);
|
const dx = common.getMax(textWidth / 2, conf.width / 2);
|
||||||
bounds.insert(
|
bounds.insert(
|
||||||
startx - dx,
|
startx - dx,
|
||||||
bounds.getVerticalPos() - 10 + totalOffset,
|
bounds.getVerticalPos() - 10 + totalOffset,
|
||||||
@@ -374,9 +389,9 @@ const drawMessage = function (diagram, msgModel, lineStartY: number, diagObj: Di
|
|||||||
.append('path')
|
.append('path')
|
||||||
.attr(
|
.attr(
|
||||||
'd',
|
'd',
|
||||||
`M ${startx},${lineStartY} H ${startx + Math.max(conf.width / 2, textWidth / 2)} V ${
|
`M ${startx},${lineStartY} H ${
|
||||||
lineStartY + 25
|
startx + common.getMax(conf.width / 2, textWidth / 2)
|
||||||
} H ${startx}`
|
} V ${lineStartY + 25} H ${startx}`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
line = diagram
|
line = diagram
|
||||||
@@ -510,7 +525,7 @@ export const drawActors = function (
|
|||||||
|
|
||||||
// Add some rendering data to the object
|
// Add some rendering data to the object
|
||||||
actor.width = actor.width || conf.width;
|
actor.width = actor.width || conf.width;
|
||||||
actor.height = Math.max(actor.height || conf.height, conf.height);
|
actor.height = common.getMax(actor.height || conf.height, conf.height);
|
||||||
actor.margin = actor.margin || conf.actorMargin;
|
actor.margin = actor.margin || conf.actorMargin;
|
||||||
|
|
||||||
actor.x = prevWidth + prevMargin;
|
actor.x = prevWidth + prevMargin;
|
||||||
@@ -518,7 +533,7 @@ export const drawActors = function (
|
|||||||
|
|
||||||
// Draw the box with the attached line
|
// Draw the box with the attached line
|
||||||
const height = svgDraw.drawActor(diagram, actor, conf, isFooter);
|
const height = svgDraw.drawActor(diagram, actor, conf, isFooter);
|
||||||
maxHeight = Math.max(maxHeight, height);
|
maxHeight = common.getMax(maxHeight, height);
|
||||||
bounds.insert(actor.x, verticalPos, actor.x + actor.width, actor.height);
|
bounds.insert(actor.x, verticalPos, actor.x + actor.width, actor.height);
|
||||||
|
|
||||||
prevWidth += actor.width + prevMargin;
|
prevWidth += actor.width + prevMargin;
|
||||||
@@ -590,10 +605,10 @@ const activationBounds = function (actor, actors) {
|
|||||||
const activations = actorActivations(actor);
|
const activations = actorActivations(actor);
|
||||||
|
|
||||||
const left = activations.reduce(function (acc, activation) {
|
const left = activations.reduce(function (acc, activation) {
|
||||||
return Math.min(acc, activation.startx);
|
return common.getMin(acc, activation.startx);
|
||||||
}, actorObj.x + actorObj.width / 2);
|
}, actorObj.x + actorObj.width / 2);
|
||||||
const right = activations.reduce(function (acc, activation) {
|
const right = activations.reduce(function (acc, activation) {
|
||||||
return Math.max(acc, activation.stopx);
|
return common.getMax(acc, activation.stopx);
|
||||||
}, actorObj.x + actorObj.width / 2);
|
}, actorObj.x + actorObj.width / 2);
|
||||||
return [left, right];
|
return [left, right];
|
||||||
};
|
};
|
||||||
@@ -610,7 +625,7 @@ function adjustLoopHeightForWrap(loopWidths, msg, preMargin, postMargin, addLoop
|
|||||||
|
|
||||||
// const lines = common.splitBreaks(msg.message).length;
|
// const lines = common.splitBreaks(msg.message).length;
|
||||||
const textDims = utils.calculateTextDimensions(msg.message, textConf);
|
const textDims = utils.calculateTextDimensions(msg.message, textConf);
|
||||||
const totalOffset = Math.max(textDims.height, conf.labelBoxHeight);
|
const totalOffset = common.getMax(textDims.height, conf.labelBoxHeight);
|
||||||
heightAdjust = postMargin + totalOffset;
|
heightAdjust = postMargin + totalOffset;
|
||||||
log.debug(`${totalOffset} - ${msg.message}`);
|
log.debug(`${totalOffset} - ${msg.message}`);
|
||||||
}
|
}
|
||||||
@@ -710,6 +725,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
|
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case diagObj.db.LINETYPE.NOTE:
|
case diagObj.db.LINETYPE.NOTE:
|
||||||
|
bounds.resetVerticalPos();
|
||||||
noteModel = msg.noteModel;
|
noteModel = msg.noteModel;
|
||||||
drawNote(diagram, noteModel);
|
drawNote(diagram, noteModel);
|
||||||
break;
|
break;
|
||||||
@@ -785,6 +801,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
bounds.models.addLoop(loopModel);
|
bounds.models.addLoop(loopModel);
|
||||||
break;
|
break;
|
||||||
case diagObj.db.LINETYPE.PAR_START:
|
case diagObj.db.LINETYPE.PAR_START:
|
||||||
|
case diagObj.db.LINETYPE.PAR_OVER_START:
|
||||||
adjustLoopHeightForWrap(
|
adjustLoopHeightForWrap(
|
||||||
loopWidths,
|
loopWidths,
|
||||||
msg,
|
msg,
|
||||||
@@ -792,6 +809,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
conf.boxMargin + conf.boxTextMargin,
|
conf.boxMargin + conf.boxTextMargin,
|
||||||
(message) => bounds.newLoop(message)
|
(message) => bounds.newLoop(message)
|
||||||
);
|
);
|
||||||
|
bounds.saveVerticalPos();
|
||||||
break;
|
break;
|
||||||
case diagObj.db.LINETYPE.PAR_AND:
|
case diagObj.db.LINETYPE.PAR_AND:
|
||||||
adjustLoopHeightForWrap(
|
adjustLoopHeightForWrap(
|
||||||
@@ -859,6 +877,7 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
default:
|
default:
|
||||||
try {
|
try {
|
||||||
// lastMsg = msg
|
// lastMsg = msg
|
||||||
|
bounds.resetVerticalPos();
|
||||||
msgModel = msg.msgModel;
|
msgModel = msg.msgModel;
|
||||||
msgModel.starty = bounds.getVerticalPos();
|
msgModel.starty = bounds.getVerticalPos();
|
||||||
msgModel.sequenceIndex = sequenceIndex;
|
msgModel.sequenceIndex = sequenceIndex;
|
||||||
@@ -1026,45 +1045,45 @@ function getMaxMessageWidthPerActor(
|
|||||||
* margin
|
* margin
|
||||||
*/
|
*/
|
||||||
if (isMessage && msg.from === actor.nextActor) {
|
if (isMessage && msg.from === actor.nextActor) {
|
||||||
maxMessageWidthPerActor[msg.to] = Math.max(
|
maxMessageWidthPerActor[msg.to] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.to] || 0,
|
maxMessageWidthPerActor[msg.to] || 0,
|
||||||
messageWidth
|
messageWidth
|
||||||
);
|
);
|
||||||
} else if (isMessage && msg.from === actor.prevActor) {
|
} else if (isMessage && msg.from === actor.prevActor) {
|
||||||
maxMessageWidthPerActor[msg.from] = Math.max(
|
maxMessageWidthPerActor[msg.from] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.from] || 0,
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
messageWidth
|
messageWidth
|
||||||
);
|
);
|
||||||
} else if (isMessage && msg.from === msg.to) {
|
} else if (isMessage && msg.from === msg.to) {
|
||||||
maxMessageWidthPerActor[msg.from] = Math.max(
|
maxMessageWidthPerActor[msg.from] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.from] || 0,
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
messageWidth / 2
|
messageWidth / 2
|
||||||
);
|
);
|
||||||
|
|
||||||
maxMessageWidthPerActor[msg.to] = Math.max(
|
maxMessageWidthPerActor[msg.to] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.to] || 0,
|
maxMessageWidthPerActor[msg.to] || 0,
|
||||||
messageWidth / 2
|
messageWidth / 2
|
||||||
);
|
);
|
||||||
} else if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
} else if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
||||||
maxMessageWidthPerActor[msg.from] = Math.max(
|
maxMessageWidthPerActor[msg.from] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.from] || 0,
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
messageWidth
|
messageWidth
|
||||||
);
|
);
|
||||||
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
|
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
|
||||||
maxMessageWidthPerActor[actor.prevActor] = Math.max(
|
maxMessageWidthPerActor[actor.prevActor] = common.getMax(
|
||||||
maxMessageWidthPerActor[actor.prevActor] || 0,
|
maxMessageWidthPerActor[actor.prevActor] || 0,
|
||||||
messageWidth
|
messageWidth
|
||||||
);
|
);
|
||||||
} else if (msg.placement === diagObj.db.PLACEMENT.OVER) {
|
} else if (msg.placement === diagObj.db.PLACEMENT.OVER) {
|
||||||
if (actor.prevActor) {
|
if (actor.prevActor) {
|
||||||
maxMessageWidthPerActor[actor.prevActor] = Math.max(
|
maxMessageWidthPerActor[actor.prevActor] = common.getMax(
|
||||||
maxMessageWidthPerActor[actor.prevActor] || 0,
|
maxMessageWidthPerActor[actor.prevActor] || 0,
|
||||||
messageWidth / 2
|
messageWidth / 2
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actor.nextActor) {
|
if (actor.nextActor) {
|
||||||
maxMessageWidthPerActor[msg.from] = Math.max(
|
maxMessageWidthPerActor[msg.from] = common.getMax(
|
||||||
maxMessageWidthPerActor[msg.from] || 0,
|
maxMessageWidthPerActor[msg.from] || 0,
|
||||||
messageWidth / 2
|
messageWidth / 2
|
||||||
);
|
);
|
||||||
@@ -1120,10 +1139,10 @@ function calculateActorMargins(
|
|||||||
const actDims = utils.calculateTextDimensions(actor.description, actorFont(conf));
|
const actDims = utils.calculateTextDimensions(actor.description, actorFont(conf));
|
||||||
actor.width = actor.wrap
|
actor.width = actor.wrap
|
||||||
? conf.width
|
? conf.width
|
||||||
: Math.max(conf.width, actDims.width + 2 * conf.wrapPadding);
|
: common.getMax(conf.width, actDims.width + 2 * conf.wrapPadding);
|
||||||
|
|
||||||
actor.height = actor.wrap ? Math.max(actDims.height, conf.height) : conf.height;
|
actor.height = actor.wrap ? common.getMax(actDims.height, conf.height) : conf.height;
|
||||||
maxHeight = Math.max(maxHeight, actor.height);
|
maxHeight = common.getMax(maxHeight, actor.height);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const actorKey in actorToMessageWidth) {
|
for (const actorKey in actorToMessageWidth) {
|
||||||
@@ -1139,14 +1158,14 @@ function calculateActorMargins(
|
|||||||
if (!nextActor) {
|
if (!nextActor) {
|
||||||
const messageWidth = actorToMessageWidth[actorKey];
|
const messageWidth = actorToMessageWidth[actorKey];
|
||||||
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2;
|
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2;
|
||||||
actor.margin = Math.max(actorWidth, conf.actorMargin);
|
actor.margin = common.getMax(actorWidth, conf.actorMargin);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const messageWidth = actorToMessageWidth[actorKey];
|
const messageWidth = actorToMessageWidth[actorKey];
|
||||||
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2 - nextActor.width / 2;
|
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2 - nextActor.width / 2;
|
||||||
|
|
||||||
actor.margin = Math.max(actorWidth, conf.actorMargin);
|
actor.margin = common.getMax(actorWidth, conf.actorMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
let maxBoxHeight = 0;
|
let maxBoxHeight = 0;
|
||||||
@@ -1162,8 +1181,8 @@ function calculateActorMargins(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const boxMsgDimensions = utils.calculateTextDimensions(box.name, textFont);
|
const boxMsgDimensions = utils.calculateTextDimensions(box.name, textFont);
|
||||||
maxBoxHeight = Math.max(boxMsgDimensions.height, maxBoxHeight);
|
maxBoxHeight = common.getMax(boxMsgDimensions.height, maxBoxHeight);
|
||||||
const minWidth = Math.max(totalWidth, boxMsgDimensions.width + 2 * conf.wrapPadding);
|
const minWidth = common.getMax(totalWidth, boxMsgDimensions.width + 2 * conf.wrapPadding);
|
||||||
box.margin = conf.boxTextMargin;
|
box.margin = conf.boxTextMargin;
|
||||||
if (totalWidth < minWidth) {
|
if (totalWidth < minWidth) {
|
||||||
const missing = (minWidth - totalWidth) / 2;
|
const missing = (minWidth - totalWidth) / 2;
|
||||||
@@ -1172,7 +1191,7 @@ function calculateActorMargins(
|
|||||||
});
|
});
|
||||||
boxes.forEach((box) => (box.textMaxHeight = maxBoxHeight));
|
boxes.forEach((box) => (box.textMaxHeight = maxBoxHeight));
|
||||||
|
|
||||||
return Math.max(maxHeight, conf.height);
|
return common.getMax(maxHeight, conf.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildNoteModel = function (msg, actors, diagObj) {
|
const buildNoteModel = function (msg, actors, diagObj) {
|
||||||
@@ -1187,7 +1206,7 @@ const buildNoteModel = function (msg, actors, diagObj) {
|
|||||||
const noteModel = {
|
const noteModel = {
|
||||||
width: shouldWrap
|
width: shouldWrap
|
||||||
? conf.width
|
? conf.width
|
||||||
: Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
: common.getMax(conf.width, textDimensions.width + 2 * conf.noteMargin),
|
||||||
height: 0,
|
height: 0,
|
||||||
startx: actors[msg.from].x,
|
startx: actors[msg.from].x,
|
||||||
stopx: 0,
|
stopx: 0,
|
||||||
@@ -1197,16 +1216,16 @@ const buildNoteModel = function (msg, actors, diagObj) {
|
|||||||
};
|
};
|
||||||
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
if (msg.placement === diagObj.db.PLACEMENT.RIGHTOF) {
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, textDimensions.width)
|
? common.getMax(conf.width, textDimensions.width)
|
||||||
: Math.max(
|
: common.getMax(
|
||||||
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
textDimensions.width + 2 * conf.noteMargin
|
textDimensions.width + 2 * conf.noteMargin
|
||||||
);
|
);
|
||||||
noteModel.startx = startx + (actors[msg.from].width + conf.actorMargin) / 2;
|
noteModel.startx = startx + (actors[msg.from].width + conf.actorMargin) / 2;
|
||||||
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
|
} else if (msg.placement === diagObj.db.PLACEMENT.LEFTOF) {
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, textDimensions.width + 2 * conf.noteMargin)
|
? common.getMax(conf.width, textDimensions.width + 2 * conf.noteMargin)
|
||||||
: Math.max(
|
: common.getMax(
|
||||||
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
actors[msg.from].width / 2 + actors[msg.to].width / 2,
|
||||||
textDimensions.width + 2 * conf.noteMargin
|
textDimensions.width + 2 * conf.noteMargin
|
||||||
);
|
);
|
||||||
@@ -1214,13 +1233,21 @@ const buildNoteModel = function (msg, actors, diagObj) {
|
|||||||
} else if (msg.to === msg.from) {
|
} else if (msg.to === msg.from) {
|
||||||
textDimensions = utils.calculateTextDimensions(
|
textDimensions = utils.calculateTextDimensions(
|
||||||
shouldWrap
|
shouldWrap
|
||||||
? utils.wrapLabel(msg.message, Math.max(conf.width, actors[msg.from].width), noteFont(conf))
|
? utils.wrapLabel(
|
||||||
|
msg.message,
|
||||||
|
common.getMax(conf.width, actors[msg.from].width),
|
||||||
|
noteFont(conf)
|
||||||
|
)
|
||||||
: msg.message,
|
: msg.message,
|
||||||
noteFont(conf)
|
noteFont(conf)
|
||||||
);
|
);
|
||||||
noteModel.width = shouldWrap
|
noteModel.width = shouldWrap
|
||||||
? Math.max(conf.width, actors[msg.from].width)
|
? common.getMax(conf.width, actors[msg.from].width)
|
||||||
: Math.max(actors[msg.from].width, conf.width, textDimensions.width + 2 * conf.noteMargin);
|
: common.getMax(
|
||||||
|
actors[msg.from].width,
|
||||||
|
conf.width,
|
||||||
|
textDimensions.width + 2 * conf.noteMargin
|
||||||
|
);
|
||||||
noteModel.startx = startx + (actors[msg.from].width - noteModel.width) / 2;
|
noteModel.startx = startx + (actors[msg.from].width - noteModel.width) / 2;
|
||||||
} else {
|
} else {
|
||||||
noteModel.width =
|
noteModel.width =
|
||||||
@@ -1272,14 +1299,14 @@ const buildMessageModel = function (msg, actors, diagObj) {
|
|||||||
if (msg.wrap && msg.message) {
|
if (msg.wrap && msg.message) {
|
||||||
msg.message = utils.wrapLabel(
|
msg.message = utils.wrapLabel(
|
||||||
msg.message,
|
msg.message,
|
||||||
Math.max(boundedWidth + 2 * conf.wrapPadding, conf.width),
|
common.getMax(boundedWidth + 2 * conf.wrapPadding, conf.width),
|
||||||
messageFont(conf)
|
messageFont(conf)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const msgDims = utils.calculateTextDimensions(msg.message, messageFont(conf));
|
const msgDims = utils.calculateTextDimensions(msg.message, messageFont(conf));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
width: Math.max(
|
width: common.getMax(
|
||||||
msg.wrap ? 0 : msgDims.width + 2 * conf.wrapPadding,
|
msg.wrap ? 0 : msgDims.width + 2 * conf.wrapPadding,
|
||||||
boundedWidth + 2 * conf.wrapPadding,
|
boundedWidth + 2 * conf.wrapPadding,
|
||||||
conf.width
|
conf.width
|
||||||
@@ -1309,6 +1336,7 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO
|
|||||||
case diagObj.db.LINETYPE.ALT_START:
|
case diagObj.db.LINETYPE.ALT_START:
|
||||||
case diagObj.db.LINETYPE.OPT_START:
|
case diagObj.db.LINETYPE.OPT_START:
|
||||||
case diagObj.db.LINETYPE.PAR_START:
|
case diagObj.db.LINETYPE.PAR_START:
|
||||||
|
case diagObj.db.LINETYPE.PAR_OVER_START:
|
||||||
case diagObj.db.LINETYPE.CRITICAL_START:
|
case diagObj.db.LINETYPE.CRITICAL_START:
|
||||||
case diagObj.db.LINETYPE.BREAK_START:
|
case diagObj.db.LINETYPE.BREAK_START:
|
||||||
stack.push({
|
stack.push({
|
||||||
@@ -1368,10 +1396,10 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO
|
|||||||
msg.noteModel = noteModel;
|
msg.noteModel = noteModel;
|
||||||
stack.forEach((stk) => {
|
stack.forEach((stk) => {
|
||||||
current = stk;
|
current = stk;
|
||||||
current.from = Math.min(current.from, noteModel.startx);
|
current.from = common.getMin(current.from, noteModel.startx);
|
||||||
current.to = Math.max(current.to, noteModel.startx + noteModel.width);
|
current.to = common.getMax(current.to, noteModel.startx + noteModel.width);
|
||||||
current.width =
|
current.width =
|
||||||
Math.max(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth;
|
common.getMax(current.width, Math.abs(current.from - current.to)) - conf.labelBoxWidth;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
msgModel = buildMessageModel(msg, actors, diagObj);
|
msgModel = buildMessageModel(msg, actors, diagObj);
|
||||||
@@ -1382,18 +1410,23 @@ const calculateLoopBounds = function (messages, actors, _maxWidthPerActor, diagO
|
|||||||
if (msgModel.startx === msgModel.stopx) {
|
if (msgModel.startx === msgModel.stopx) {
|
||||||
const from = actors[msg.from];
|
const from = actors[msg.from];
|
||||||
const to = actors[msg.to];
|
const to = actors[msg.to];
|
||||||
current.from = Math.min(
|
current.from = common.getMin(
|
||||||
from.x - msgModel.width / 2,
|
from.x - msgModel.width / 2,
|
||||||
from.x - from.width / 2,
|
from.x - from.width / 2,
|
||||||
current.from
|
current.from
|
||||||
);
|
);
|
||||||
current.to = Math.max(to.x + msgModel.width / 2, to.x + from.width / 2, current.to);
|
current.to = common.getMax(
|
||||||
|
to.x + msgModel.width / 2,
|
||||||
|
to.x + from.width / 2,
|
||||||
|
current.to
|
||||||
|
);
|
||||||
current.width =
|
current.width =
|
||||||
Math.max(current.width, Math.abs(current.to - current.from)) - conf.labelBoxWidth;
|
common.getMax(current.width, Math.abs(current.to - current.from)) -
|
||||||
|
conf.labelBoxWidth;
|
||||||
} else {
|
} else {
|
||||||
current.from = Math.min(msgModel.startx, current.from);
|
current.from = common.getMin(msgModel.startx, current.from);
|
||||||
current.to = Math.max(msgModel.stopx, current.to);
|
current.to = common.getMax(msgModel.stopx, current.to);
|
||||||
current.width = Math.max(current.width, msgModel.width) - conf.labelBoxWidth;
|
current.width = common.getMax(current.width, msgModel.width) - conf.labelBoxWidth;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user