Add lost message arrow style [#38]
This commit is contained in:
parent
0c988e8658
commit
afd505b8fe
|
@ -60,6 +60,8 @@ Bar -> Bar: Bar talks to itself
|
|||
Foo -> +Bar: Foo asks Bar
|
||||
-Bar --> Foo: and Bar replies
|
||||
|
||||
Bar -x Baz: Lost message
|
||||
|
||||
# Arrows leaving on the left and right of the diagram
|
||||
[ -> Foo: From the left
|
||||
[ <- Foo: To the left
|
||||
|
|
|
@ -1053,8 +1053,11 @@ define('sequence/CodeMirrorMode',['core/ArrayUtilities'], (array) => {
|
|||
});
|
||||
}
|
||||
|
||||
_tokenEndFound(stream, state, block) {
|
||||
_tokenEndFound(stream, state, block, match) {
|
||||
state.currentType = -1;
|
||||
if(block.includeEnd) {
|
||||
state.current += match[0];
|
||||
}
|
||||
if(block.omit) {
|
||||
return 'comment';
|
||||
}
|
||||
|
@ -1077,8 +1080,13 @@ define('sequence/CodeMirrorMode',['core/ArrayUtilities'], (array) => {
|
|||
while(true) {
|
||||
const block = this.tokenDefinitions[state.currentType];
|
||||
this._tokenCheckEscape(stream, state, block);
|
||||
if(!block.end || this._matchPattern(stream, block.end, true)) {
|
||||
return this._tokenEndFound(stream, state, block);
|
||||
if(!block.end) {
|
||||
return this._tokenEndFound(stream, state, block, null);
|
||||
} else {
|
||||
const match = this._matchPattern(stream, block.end, true);
|
||||
if(match) {
|
||||
return this._tokenEndFound(stream, state, block, match);
|
||||
}
|
||||
}
|
||||
if(stream.eol()) {
|
||||
return this._tokenEOLFound(stream, state, block);
|
||||
|
@ -1143,7 +1151,11 @@ define('sequence/Tokeniser',['./CodeMirrorMode'], (CMMode) => {
|
|||
baseToken: {q: true},
|
||||
},
|
||||
{start: /(?=[^ \t\r\n:+\-~*!<>,])/y, end: /(?=[ \t\r\n:+\-~*!<>,])|$/y},
|
||||
{start: /(?=[\-~<>])/y, end: /(?=[^\-~<>])|$/y},
|
||||
{
|
||||
start: /(?=[\-~<])/y,
|
||||
end: /(?=[^\-~<>x])|[\-~]x|[<>](?=x)|$/y,
|
||||
includeEnd: true,
|
||||
},
|
||||
{start: /,/y, baseToken: {v: ','}},
|
||||
{start: /:/y, baseToken: {v: ':'}},
|
||||
{start: /!/y, baseToken: {v: '!'}},
|
||||
|
@ -1194,7 +1206,7 @@ define('sequence/Tokeniser',['./CodeMirrorMode'], (CMMode) => {
|
|||
newBlock: null,
|
||||
end: true,
|
||||
appendSpace: '',
|
||||
appendValue: '',
|
||||
appendValue: block.includeEnd ? match[0] : '',
|
||||
skip: match[0].length,
|
||||
};
|
||||
}
|
||||
|
@ -1565,6 +1577,7 @@ define('sequence/Parser',[
|
|||
{tok: '', type: 0},
|
||||
{tok: '>', type: 1},
|
||||
{tok: '>>', type: 2},
|
||||
{tok: 'x', type: 3},
|
||||
];
|
||||
const arrows = (array.combine([lTypes, mTypes, rTypes])
|
||||
.filter((arrow) => (arrow[0].type !== 0 || arrow[2].type !== 0))
|
||||
|
@ -4264,6 +4277,34 @@ define('sequence/components/Connect',[
|
|||
}
|
||||
}
|
||||
|
||||
class Arrowcross {
|
||||
getConfig(theme) {
|
||||
return theme.connect.arrow.cross;
|
||||
}
|
||||
|
||||
render(layer, theme, pt, dir) {
|
||||
const config = this.getConfig(theme);
|
||||
layer.appendChild(config.render({
|
||||
x: pt.x + config.short * dir,
|
||||
y: pt.y,
|
||||
radius: config.radius,
|
||||
}));
|
||||
}
|
||||
|
||||
width(theme) {
|
||||
const config = this.getConfig(theme);
|
||||
return config.short + config.radius;
|
||||
}
|
||||
|
||||
height(theme) {
|
||||
return this.getConfig(theme).radius * 2;
|
||||
}
|
||||
|
||||
lineGap(theme) {
|
||||
return this.getConfig(theme).short;
|
||||
}
|
||||
}
|
||||
|
||||
const ARROWHEADS = [
|
||||
{
|
||||
render: () => {},
|
||||
|
@ -4273,6 +4314,7 @@ define('sequence/components/Connect',[
|
|||
},
|
||||
new Arrowhead('single'),
|
||||
new Arrowhead('double'),
|
||||
new Arrowcross(),
|
||||
];
|
||||
|
||||
class Connect extends BaseComponent {
|
||||
|
@ -5839,6 +5881,15 @@ define('sequence/themes/Basic',[
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 7,
|
||||
radius: 3,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 6,
|
||||
|
@ -6151,6 +6202,15 @@ define('sequence/themes/Monospace',[
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 8,
|
||||
radius: 4,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 4,
|
||||
|
@ -6437,7 +6497,7 @@ define('sequence/themes/Chunky',[
|
|||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 10,
|
||||
height: 12,
|
||||
render: BaseTheme.renderHorizArrowHead,
|
||||
|
@ -6448,7 +6508,7 @@ define('sequence/themes/Chunky',[
|
|||
'stroke-linejoin': 'round',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
'double': {
|
||||
width: 10,
|
||||
height: 12,
|
||||
render: BaseTheme.renderHorizArrowHead,
|
||||
|
@ -6460,6 +6520,17 @@ define('sequence/themes/Chunky',[
|
|||
'stroke-linecap': 'round',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 10,
|
||||
radius: 5,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 7,
|
||||
|
@ -7195,6 +7266,11 @@ define('sequence/themes/Sketch',[
|
|||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
'cross': {
|
||||
short: 5,
|
||||
radius: 3,
|
||||
render: null,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 6,
|
||||
|
@ -7432,6 +7508,7 @@ define('sequence/themes/Sketch',[
|
|||
|
||||
this.connect.arrow.single.render = this.renderArrowHead;
|
||||
this.connect.arrow.double.render = this.renderArrowHead;
|
||||
this.connect.arrow.cross.render = this.renderCross.bind(this);
|
||||
|
||||
this.connect.line.solid.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.solid.renderRev = this.renderRevConnector;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -174,6 +174,8 @@ Bar -> Bar: Bar talks to itself
|
|||
Foo -> +Bar: Foo asks Bar
|
||||
-Bar --> Foo: and Bar replies
|
||||
|
||||
Bar -x Baz: Lost message
|
||||
|
||||
# Arrows leaving on the left and right of the diagram
|
||||
[ -> Foo: From the left
|
||||
[ <- Foo: To the left
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 62 KiB |
|
@ -33,17 +33,21 @@
|
|||
);
|
||||
const library = [
|
||||
{
|
||||
title: 'Simple arrow',
|
||||
title: 'Simple arrow (synchronous)',
|
||||
code: '{Agent1} -> {Agent2}: {Message}',
|
||||
},
|
||||
{
|
||||
title: 'Arrow with dotted line',
|
||||
title: 'Arrow with dotted line (response)',
|
||||
code: '{Agent1} --> {Agent2}: {Message}',
|
||||
},
|
||||
{
|
||||
title: 'Open arrow',
|
||||
title: 'Open arrow (asynchronous)',
|
||||
code: '{Agent1} ->> {Agent2}: {Message}',
|
||||
},
|
||||
{
|
||||
title: 'Lost message',
|
||||
code: '{Agent1} -x {Agent2}: {Message}',
|
||||
},
|
||||
{
|
||||
title: 'Wavy line',
|
||||
code: '{Agent1} ~> {Agent2}: {Message}',
|
||||
|
@ -114,7 +118,7 @@
|
|||
),
|
||||
},
|
||||
{
|
||||
title: 'Repeated blocks',
|
||||
title: 'Repeated block',
|
||||
code: (
|
||||
'repeat {Condition}\n' +
|
||||
' {Agent1} -> {Agent2}\n' +
|
||||
|
@ -128,7 +132,7 @@
|
|||
),
|
||||
},
|
||||
{
|
||||
title: 'References',
|
||||
title: 'Reference',
|
||||
code: (
|
||||
'begin reference: {Label} as {Name}\n' +
|
||||
'{Agent1} -> {Name}\n' +
|
||||
|
@ -143,7 +147,7 @@
|
|||
),
|
||||
},
|
||||
{
|
||||
title: 'References over agents',
|
||||
title: 'Reference over agents',
|
||||
code: (
|
||||
'begin reference over {Covered}: {Label} as {Name}\n' +
|
||||
'{Agent1} -> {Name}\n' +
|
||||
|
|
|
@ -450,8 +450,11 @@ define(['core/ArrayUtilities'], (array) => {
|
|||
});
|
||||
}
|
||||
|
||||
_tokenEndFound(stream, state, block) {
|
||||
_tokenEndFound(stream, state, block, match) {
|
||||
state.currentType = -1;
|
||||
if(block.includeEnd) {
|
||||
state.current += match[0];
|
||||
}
|
||||
if(block.omit) {
|
||||
return 'comment';
|
||||
}
|
||||
|
@ -474,8 +477,13 @@ define(['core/ArrayUtilities'], (array) => {
|
|||
while(true) {
|
||||
const block = this.tokenDefinitions[state.currentType];
|
||||
this._tokenCheckEscape(stream, state, block);
|
||||
if(!block.end || this._matchPattern(stream, block.end, true)) {
|
||||
return this._tokenEndFound(stream, state, block);
|
||||
if(!block.end) {
|
||||
return this._tokenEndFound(stream, state, block, null);
|
||||
} else {
|
||||
const match = this._matchPattern(stream, block.end, true);
|
||||
if(match) {
|
||||
return this._tokenEndFound(stream, state, block, match);
|
||||
}
|
||||
}
|
||||
if(stream.eol()) {
|
||||
return this._tokenEOLFound(stream, state, block);
|
||||
|
|
|
@ -47,6 +47,7 @@ define([
|
|||
{tok: '', type: 0},
|
||||
{tok: '>', type: 1},
|
||||
{tok: '>>', type: 2},
|
||||
{tok: 'x', type: 3},
|
||||
];
|
||||
const arrows = (array.combine([lTypes, mTypes, rTypes])
|
||||
.filter((arrow) => (arrow[0].type !== 0 || arrow[2].type !== 0))
|
||||
|
|
|
@ -219,6 +219,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
'A<<-B\n' +
|
||||
'A<<->B\n' +
|
||||
'A<<->>B\n' +
|
||||
'A-xB\n' +
|
||||
'A-->B\n' +
|
||||
'A-->>B\n' +
|
||||
'A<--B\n' +
|
||||
|
@ -227,6 +228,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
'A<<--B\n' +
|
||||
'A<<-->B\n' +
|
||||
'A<<-->>B\n' +
|
||||
'A--xB\n' +
|
||||
'A~>B\n' +
|
||||
'A~>>B\n' +
|
||||
'A<~B\n' +
|
||||
|
@ -234,7 +236,8 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
'A<~>>B\n' +
|
||||
'A<<~B\n' +
|
||||
'A<<~>B\n' +
|
||||
'A<<~>>B\n'
|
||||
'A<<~>>B\n' +
|
||||
'A~xB\n'
|
||||
);
|
||||
expect(parsed.stages).toEqual([
|
||||
PARSED.connect(['A', 'B'], {
|
||||
|
@ -250,6 +253,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 0}),
|
||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 1}),
|
||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 2}),
|
||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 0, right: 3}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 0, right: 1}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 0, right: 2}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 0}),
|
||||
|
@ -258,6 +262,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 0}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 1}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 2}),
|
||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 0, right: 3}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 0, right: 1}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 0, right: 2}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 1, right: 0}),
|
||||
|
@ -266,6 +271,7 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
|||
PARSED.connect(['A', 'B'], {line: 'wave', left: 2, right: 0}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 2, right: 1}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 2, right: 2}),
|
||||
PARSED.connect(['A', 'B'], {line: 'wave', left: 0, right: 3}),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -32,7 +32,11 @@ define(['./CodeMirrorMode'], (CMMode) => {
|
|||
baseToken: {q: true},
|
||||
},
|
||||
{start: /(?=[^ \t\r\n:+\-~*!<>,])/y, end: /(?=[ \t\r\n:+\-~*!<>,])|$/y},
|
||||
{start: /(?=[\-~<>])/y, end: /(?=[^\-~<>])|$/y},
|
||||
{
|
||||
start: /(?=[\-~<])/y,
|
||||
end: /(?=[^\-~<>x])|[\-~]x|[<>](?=x)|$/y,
|
||||
includeEnd: true,
|
||||
},
|
||||
{start: /,/y, baseToken: {v: ','}},
|
||||
{start: /:/y, baseToken: {v: ':'}},
|
||||
{start: /!/y, baseToken: {v: '!'}},
|
||||
|
@ -83,7 +87,7 @@ define(['./CodeMirrorMode'], (CMMode) => {
|
|||
newBlock: null,
|
||||
end: true,
|
||||
appendSpace: '',
|
||||
appendValue: '',
|
||||
appendValue: block.includeEnd ? match[0] : '',
|
||||
skip: match[0].length,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -174,6 +174,38 @@ defineDescribe('Sequence Tokeniser', ['./Tokeniser'], (Tokeniser) => {
|
|||
'Unterminated literal (began at line 1, character 0)'
|
||||
));
|
||||
});
|
||||
|
||||
it('stops tokenising arrows once they become invalid', () => {
|
||||
expect(tokeniser.tokenise('foo -> bar')).toEqual([
|
||||
token({s: '', v: 'foo'}),
|
||||
token({s: ' ', v: '->'}),
|
||||
token({s: ' ', v: 'bar'}),
|
||||
]);
|
||||
|
||||
expect(tokeniser.tokenise('foo->bar')).toEqual([
|
||||
token({s: '', v: 'foo'}),
|
||||
token({s: '', v: '->'}),
|
||||
token({s: '', v: 'bar'}),
|
||||
]);
|
||||
|
||||
expect(tokeniser.tokenise('foo-xbar')).toEqual([
|
||||
token({s: '', v: 'foo'}),
|
||||
token({s: '', v: '-x'}),
|
||||
token({s: '', v: 'bar'}),
|
||||
]);
|
||||
|
||||
expect(tokeniser.tokenise('foo-xxyz')).toEqual([
|
||||
token({s: '', v: 'foo'}),
|
||||
token({s: '', v: '-x'}),
|
||||
token({s: '', v: 'xyz'}),
|
||||
]);
|
||||
|
||||
expect(tokeniser.tokenise('foo->xyz')).toEqual([
|
||||
token({s: '', v: 'foo'}),
|
||||
token({s: '', v: '->'}),
|
||||
token({s: '', v: 'xyz'}),
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.splitLines', () => {
|
||||
|
|
|
@ -65,6 +65,34 @@ define([
|
|||
}
|
||||
}
|
||||
|
||||
class Arrowcross {
|
||||
getConfig(theme) {
|
||||
return theme.connect.arrow.cross;
|
||||
}
|
||||
|
||||
render(layer, theme, pt, dir) {
|
||||
const config = this.getConfig(theme);
|
||||
layer.appendChild(config.render({
|
||||
x: pt.x + config.short * dir,
|
||||
y: pt.y,
|
||||
radius: config.radius,
|
||||
}));
|
||||
}
|
||||
|
||||
width(theme) {
|
||||
const config = this.getConfig(theme);
|
||||
return config.short + config.radius;
|
||||
}
|
||||
|
||||
height(theme) {
|
||||
return this.getConfig(theme).radius * 2;
|
||||
}
|
||||
|
||||
lineGap(theme) {
|
||||
return this.getConfig(theme).short;
|
||||
}
|
||||
}
|
||||
|
||||
const ARROWHEADS = [
|
||||
{
|
||||
render: () => {},
|
||||
|
@ -74,6 +102,7 @@ define([
|
|||
},
|
||||
new Arrowhead('single'),
|
||||
new Arrowhead('double'),
|
||||
new Arrowcross(),
|
||||
];
|
||||
|
||||
class Connect extends BaseComponent {
|
||||
|
|
|
@ -125,6 +125,15 @@ define([
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 7,
|
||||
radius: 3,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 6,
|
||||
|
|
|
@ -110,7 +110,7 @@ define([
|
|||
},
|
||||
},
|
||||
arrow: {
|
||||
single: {
|
||||
'single': {
|
||||
width: 10,
|
||||
height: 12,
|
||||
render: BaseTheme.renderHorizArrowHead,
|
||||
|
@ -121,7 +121,7 @@ define([
|
|||
'stroke-linejoin': 'round',
|
||||
},
|
||||
},
|
||||
double: {
|
||||
'double': {
|
||||
width: 10,
|
||||
height: 12,
|
||||
render: BaseTheme.renderHorizArrowHead,
|
||||
|
@ -133,6 +133,17 @@ define([
|
|||
'stroke-linecap': 'round',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 10,
|
||||
radius: 5,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 3,
|
||||
'stroke-linejoin': 'round',
|
||||
'stroke-linecap': 'round',
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 7,
|
||||
|
|
|
@ -132,6 +132,15 @@ define([
|
|||
'stroke-linejoin': 'miter',
|
||||
},
|
||||
},
|
||||
'cross': {
|
||||
short: 8,
|
||||
radius: 4,
|
||||
render: BaseTheme.renderCross.bind(null, {
|
||||
'fill': 'none',
|
||||
'stroke': '#000000',
|
||||
'stroke-width': 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 4,
|
||||
|
|
|
@ -118,6 +118,11 @@ define([
|
|||
}, PENCIL),
|
||||
render: null,
|
||||
},
|
||||
'cross': {
|
||||
short: 5,
|
||||
radius: 3,
|
||||
render: null,
|
||||
},
|
||||
},
|
||||
label: {
|
||||
padding: 6,
|
||||
|
@ -355,6 +360,7 @@ define([
|
|||
|
||||
this.connect.arrow.single.render = this.renderArrowHead;
|
||||
this.connect.arrow.double.render = this.renderArrowHead;
|
||||
this.connect.arrow.cross.render = this.renderCross.bind(this);
|
||||
|
||||
this.connect.line.solid.renderFlat = this.renderFlatConnector;
|
||||
this.connect.line.solid.renderRev = this.renderRevConnector;
|
||||
|
|
Loading…
Reference in New Issue