Add support for wavy connection lines [#24]
This commit is contained in:
parent
16095cf78a
commit
5b3d0af311
|
@ -65,7 +65,7 @@ Foo -> +Bar: Foo asks Bar
|
||||||
[ <- Foo: To the left
|
[ <- Foo: To the left
|
||||||
Foo -> ]: To the right
|
Foo -> ]: To the right
|
||||||
Foo <- ]: From the right
|
Foo <- ]: From the right
|
||||||
[ -> ]: Left to right!
|
[ ~> ]: Wavy left to right!
|
||||||
# (etc.)
|
# (etc.)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 59 KiB |
|
@ -56,24 +56,28 @@ define(() => {
|
||||||
return list[list.length - 1];
|
return list[list.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
function combineRecur(parts, position, str, target) {
|
function combineRecur(parts, position, current, target) {
|
||||||
if(position >= parts.length) {
|
if(position >= parts.length) {
|
||||||
target.push(str);
|
target.push(current.slice());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const choices = parts[position];
|
const choices = parts[position];
|
||||||
if(!Array.isArray(choices)) {
|
if(!Array.isArray(choices)) {
|
||||||
combineRecur(parts, position + 1, str + choices, target);
|
current.push(choices);
|
||||||
|
combineRecur(parts, position + 1, current, target);
|
||||||
|
current.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(let i = 0; i < choices.length; ++ i) {
|
for(let i = 0; i < choices.length; ++ i) {
|
||||||
combineRecur(parts, position + 1, str + choices[i], target);
|
current.push(choices[i]);
|
||||||
|
combineRecur(parts, position + 1, current, target);
|
||||||
|
current.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function combine(parts) {
|
function combine(parts) {
|
||||||
const target = [];
|
const target = [];
|
||||||
combineRecur(parts, 0, '', target);
|
combineRecur(parts, 0, [], target);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,10 +179,10 @@ defineDescribe('ArrayUtilities', ['./ArrayUtilities'], (array) => {
|
||||||
['Ff'],
|
['Ff'],
|
||||||
]);
|
]);
|
||||||
expect(list).toEqual([
|
expect(list).toEqual([
|
||||||
'AaCcEeFf',
|
['Aa', 'Cc', 'Ee', 'Ff'],
|
||||||
'AaDdEeFf',
|
['Aa', 'Dd', 'Ee', 'Ff'],
|
||||||
'BbCcEeFf',
|
['Bb', 'Cc', 'Ee', 'Ff'],
|
||||||
'BbDdEeFf',
|
['Bb', 'Dd', 'Ee', 'Ff'],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -53,6 +53,10 @@
|
||||||
title: 'Open arrow',
|
title: 'Open arrow',
|
||||||
code: '{Agent1} ->> {Agent2}: {Message}',
|
code: '{Agent1} ->> {Agent2}: {Message}',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: 'Wavy line',
|
||||||
|
code: '{Agent1} ~> {Agent2}: {Message}',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: 'Self-connection',
|
title: 'Self-connection',
|
||||||
code: '{Agent1} -> {Agent1}: {Message}',
|
code: '{Agent1} -> {Agent1}: {Message}',
|
||||||
|
|
|
@ -3,17 +3,10 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
|
|
||||||
const CM_ERROR = {type: 'error line-error', then: {'': 0}};
|
const CM_ERROR = {type: 'error line-error', then: {'': 0}};
|
||||||
|
|
||||||
const CM_COMMANDS = ((() => {
|
const makeCommands = ((() => {
|
||||||
const end = {type: '', suggest: '\n', then: {}};
|
const end = {type: '', suggest: '\n', then: {}};
|
||||||
const hiddenEnd = {type: '', then: {}};
|
const hiddenEnd = {type: '', then: {}};
|
||||||
|
|
||||||
const ARROWS = array.combine([
|
|
||||||
['', '<', '<<'],
|
|
||||||
['-', '--'],
|
|
||||||
['', '>', '>>'],
|
|
||||||
]);
|
|
||||||
array.removeAll(ARROWS, ['-', '--']);
|
|
||||||
|
|
||||||
const textToEnd = {type: 'string', then: {'': 0, '\n': end}};
|
const textToEnd = {type: 'string', then: {'': 0, '\n': end}};
|
||||||
const aliasListToEnd = {type: 'variable', suggest: 'Agent', then: {
|
const aliasListToEnd = {type: 'variable', suggest: 'Agent', then: {
|
||||||
'': 0,
|
'': 0,
|
||||||
|
@ -108,7 +101,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeCMConnect() {
|
function makeCMConnect(arrows) {
|
||||||
const connect = {
|
const connect = {
|
||||||
type: 'keyword',
|
type: 'keyword',
|
||||||
suggest: true,
|
suggest: true,
|
||||||
|
@ -124,11 +117,11 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
},
|
},
|
||||||
'': 0,
|
'': 0,
|
||||||
};
|
};
|
||||||
ARROWS.forEach((arrow) => (then[arrow] = connect));
|
arrows.forEach((arrow) => (then[arrow] = connect));
|
||||||
return makeOpBlock({type: 'variable', suggest: 'Agent', then});
|
return makeOpBlock({type: 'variable', suggest: 'Agent', then});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {type: 'error line-error', then: Object.assign({
|
const BASE_THEN = {
|
||||||
'title': {type: 'keyword', suggest: true, then: {
|
'title': {type: 'keyword', suggest: true, then: {
|
||||||
'': textToEnd,
|
'': textToEnd,
|
||||||
}},
|
}},
|
||||||
|
@ -220,7 +213,14 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}},
|
}},
|
||||||
}, makeCMConnect())};
|
};
|
||||||
|
|
||||||
|
return (arrows) => {
|
||||||
|
return {
|
||||||
|
type: 'error line-error',
|
||||||
|
then: Object.assign(BASE_THEN, makeCMConnect(arrows)),
|
||||||
|
};
|
||||||
|
};
|
||||||
})());
|
})());
|
||||||
|
|
||||||
function cmCappedToken(token, current) {
|
function cmCappedToken(token, current) {
|
||||||
|
@ -294,12 +294,12 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmCheckToken(state, eol) {
|
function cmCheckToken(state, eol, commands) {
|
||||||
const suggestions = {
|
const suggestions = {
|
||||||
type: '',
|
type: '',
|
||||||
value: '',
|
value: '',
|
||||||
};
|
};
|
||||||
let current = CM_COMMANDS;
|
let current = commands;
|
||||||
const path = [current];
|
const path = [current];
|
||||||
|
|
||||||
state.line.forEach((token, i) => {
|
state.line.forEach((token, i) => {
|
||||||
|
@ -336,8 +336,9 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return class Mode {
|
return class Mode {
|
||||||
constructor(tokenDefinitions) {
|
constructor(tokenDefinitions, arrows) {
|
||||||
this.tokenDefinitions = tokenDefinitions;
|
this.tokenDefinitions = tokenDefinitions;
|
||||||
|
this.commands = makeCommands(arrows);
|
||||||
this.lineComment = '#';
|
this.lineComment = '#';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +349,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
currentQuoted: false,
|
currentQuoted: false,
|
||||||
knownAgent: [],
|
knownAgent: [],
|
||||||
knownLabel: [],
|
knownLabel: [],
|
||||||
beginCompletions: cmMakeCompletions({}, [CM_COMMANDS]),
|
beginCompletions: cmMakeCompletions({}, [this.commands]),
|
||||||
completions: [],
|
completions: [],
|
||||||
nextCompletions: [],
|
nextCompletions: [],
|
||||||
valid: true,
|
valid: true,
|
||||||
|
@ -397,7 +398,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
return 'comment';
|
return 'comment';
|
||||||
}
|
}
|
||||||
state.line.push({v: state.current, q: state.currentQuoted});
|
state.line.push({v: state.current, q: state.currentQuoted});
|
||||||
return cmCheckToken(state, stream.eol());
|
return cmCheckToken(state, stream.eol(), this.commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
_tokenEOLFound(stream, state, block) {
|
_tokenEOLFound(stream, state, block) {
|
||||||
|
@ -406,7 +407,7 @@ define(['core/ArrayUtilities'], (array) => {
|
||||||
return 'comment';
|
return 'comment';
|
||||||
}
|
}
|
||||||
state.line.push(({v: state.current, q: state.currentQuoted}));
|
state.line.push(({v: state.current, q: state.currentQuoted}));
|
||||||
const type = cmCheckToken(state, false);
|
const type = cmCheckToken(state, false, this.commands);
|
||||||
state.line.pop();
|
state.line.pop();
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,32 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
const CONNECT_TYPES = ((() => {
|
const CONNECT_TYPES = ((() => {
|
||||||
const lTypes = ['', '<', '<<'];
|
const lTypes = [
|
||||||
const mTypes = ['-', '--'];
|
{tok: '', type: 0},
|
||||||
const rTypes = ['', '>', '>>'];
|
{tok: '<', type: 1},
|
||||||
const arrows = array.combine([lTypes, mTypes, rTypes]);
|
{tok: '<<', type: 2},
|
||||||
array.removeAll(arrows, mTypes);
|
];
|
||||||
|
const mTypes = [
|
||||||
|
{tok: '-', type: 'solid'},
|
||||||
|
{tok: '--', type: 'dash'},
|
||||||
|
{tok: '~', type: 'wave'},
|
||||||
|
];
|
||||||
|
const rTypes = [
|
||||||
|
{tok: '', type: 0},
|
||||||
|
{tok: '>', type: 1},
|
||||||
|
{tok: '>>', type: 2},
|
||||||
|
];
|
||||||
|
const arrows = (array.combine([lTypes, mTypes, rTypes])
|
||||||
|
.filter((arrow) => (arrow[0].type !== 0 || arrow[2].type !== 0))
|
||||||
|
);
|
||||||
|
|
||||||
const types = new Map();
|
const types = new Map();
|
||||||
|
|
||||||
arrows.forEach((arrow) => {
|
arrows.forEach((arrow) => {
|
||||||
types.set(arrow, {
|
types.set(arrow.map((part) => part.tok).join(''), {
|
||||||
line: arrow.includes('--') ? 'dash' : 'solid',
|
line: arrow[1].type,
|
||||||
left: lTypes.indexOf(arrow.substr(0, arrow.indexOf('-'))),
|
left: arrow[0].type,
|
||||||
right: rTypes.indexOf(arrow.substr(arrow.lastIndexOf('-') + 1)),
|
right: arrow[2].type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -411,7 +424,9 @@ define([
|
||||||
|
|
||||||
return class Parser {
|
return class Parser {
|
||||||
getCodeMirrorMode() {
|
getCodeMirrorMode() {
|
||||||
return SHARED_TOKENISER.getCodeMirrorMode();
|
return SHARED_TOKENISER.getCodeMirrorMode(
|
||||||
|
Array.from(CONNECT_TYPES.keys())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCodeMirrorHints() {
|
getCodeMirrorHints() {
|
||||||
|
|
|
@ -195,22 +195,30 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
|
|
||||||
it('recognises all types of connection', () => {
|
it('recognises all types of connection', () => {
|
||||||
const parsed = parser.parse(
|
const parsed = parser.parse(
|
||||||
'A -> B\n' +
|
'A->B\n' +
|
||||||
'A <- B\n' +
|
'A->>B\n' +
|
||||||
'A <-> B\n' +
|
'A<-B\n' +
|
||||||
'A --> B\n' +
|
'A<->B\n' +
|
||||||
'A <-- B\n' +
|
'A<->>B\n' +
|
||||||
'A <--> B\n' +
|
'A<<-B\n' +
|
||||||
'A ->> B\n' +
|
'A<<->B\n' +
|
||||||
'A <<- B\n' +
|
'A<<->>B\n' +
|
||||||
'A <<->> B\n' +
|
'A-->B\n' +
|
||||||
'A <->> B\n' +
|
'A-->>B\n' +
|
||||||
'A <<-> B\n' +
|
'A<--B\n' +
|
||||||
'A -->> B\n' +
|
'A<-->B\n' +
|
||||||
'A <<-- B\n' +
|
'A<-->>B\n' +
|
||||||
'A <<-->> B\n' +
|
'A<<--B\n' +
|
||||||
'A <-->> B\n' +
|
'A<<-->B\n' +
|
||||||
'A <<--> B\n'
|
'A<<-->>B\n' +
|
||||||
|
'A~>B\n' +
|
||||||
|
'A~>>B\n' +
|
||||||
|
'A<~B\n' +
|
||||||
|
'A<~>B\n' +
|
||||||
|
'A<~>>B\n' +
|
||||||
|
'A<<~B\n' +
|
||||||
|
'A<<~>B\n' +
|
||||||
|
'A<<~>>B\n'
|
||||||
);
|
);
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
PARSED.connect(['A', 'B'], {
|
PARSED.connect(['A', 'B'], {
|
||||||
|
@ -219,21 +227,29 @@ defineDescribe('Sequence Parser', ['./Parser'], (Parser) => {
|
||||||
right: 1,
|
right: 1,
|
||||||
label: '',
|
label: '',
|
||||||
}),
|
}),
|
||||||
|
PARSED.connect(['A', 'B'], {line: 'solid', left: 0, right: 2}),
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 0}),
|
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 1}),
|
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 2}),
|
||||||
|
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: 'dash', left: 0, right: 1}),
|
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}),
|
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 1}),
|
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 0, right: 2}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 0}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 2}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 1, right: 2}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'solid', left: 2, right: 1}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 0, right: 2}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 0}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 2}),
|
|
||||||
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 2}),
|
PARSED.connect(['A', 'B'], {line: 'dash', left: 1, right: 2}),
|
||||||
|
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: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {line: 'dash', left: 2, right: 2}),
|
||||||
|
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}),
|
||||||
|
PARSED.connect(['A', 'B'], {line: 'wave', left: 1, right: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {line: 'wave', left: 1, right: 2}),
|
||||||
|
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}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,8 @@ define(['./CodeMirrorMode'], (CMMode) => {
|
||||||
unescape,
|
unescape,
|
||||||
baseToken: {q: true},
|
baseToken: {q: true},
|
||||||
},
|
},
|
||||||
{start: /(?=[^ \t\r\n:+\-*!<>,])/y, end: /(?=[ \t\r\n:+\-*!<>,])|$/y},
|
{start: /(?=[^ \t\r\n:+\-~*!<>,])/y, end: /(?=[ \t\r\n:+\-~*!<>,])|$/y},
|
||||||
{start: /(?=[\-<>])/y, end: /(?=[^\-<>])|$/y},
|
{start: /(?=[\-~<>])/y, end: /(?=[^\-~<>])|$/y},
|
||||||
{start: /,/y, baseToken: {v: ','}},
|
{start: /,/y, baseToken: {v: ','}},
|
||||||
{start: /:/y, baseToken: {v: ':'}},
|
{start: /:/y, baseToken: {v: ':'}},
|
||||||
{start: /!/y, baseToken: {v: '!'}},
|
{start: /!/y, baseToken: {v: '!'}},
|
||||||
|
@ -195,8 +195,8 @@ define(['./CodeMirrorMode'], (CMMode) => {
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCodeMirrorMode() {
|
getCodeMirrorMode(arrows) {
|
||||||
return new CMMode(TOKENS);
|
return new CMMode(TOKENS, arrows);
|
||||||
}
|
}
|
||||||
|
|
||||||
splitLines(tokens) {
|
splitLines(tokens) {
|
||||||
|
|
|
@ -90,6 +90,105 @@ define([
|
||||||
new Arrowhead('double'),
|
new Arrowhead('double'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function makeWavyLineHeights(height) {
|
||||||
|
return [
|
||||||
|
0,
|
||||||
|
-height * 2 / 3,
|
||||||
|
-height,
|
||||||
|
-height * 2 / 3,
|
||||||
|
0,
|
||||||
|
height * 2 / 3,
|
||||||
|
height,
|
||||||
|
height * 2 / 3,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConnectingLine {
|
||||||
|
renderFlat(container, {x1, x2, y}, attrs) {
|
||||||
|
const ww = attrs['wave-width'];
|
||||||
|
const hh = attrs['wave-height'];
|
||||||
|
|
||||||
|
if(!ww || !hh) {
|
||||||
|
container.appendChild(svg.make('line', Object.assign({
|
||||||
|
'x1': x1,
|
||||||
|
'y1': y,
|
||||||
|
'x2': x2,
|
||||||
|
'y2': y,
|
||||||
|
}, attrs)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const heights = makeWavyLineHeights(hh);
|
||||||
|
const dw = ww / heights.length;
|
||||||
|
let p = 0;
|
||||||
|
|
||||||
|
let points = '';
|
||||||
|
for(let x = x1; x + dw <= x2; x += dw) {
|
||||||
|
points += (
|
||||||
|
x + ' ' +
|
||||||
|
(y + heights[(p ++) % heights.length]) + ' '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
points += x2 + ' ' + y;
|
||||||
|
container.appendChild(svg.make('polyline', Object.assign({
|
||||||
|
points,
|
||||||
|
}, attrs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
renderRev(container, {xL1, xL2, y1, y2, xR}, attrs) {
|
||||||
|
const r = (y2 - y1) / 2;
|
||||||
|
const ww = attrs['wave-width'];
|
||||||
|
const hh = attrs['wave-height'];
|
||||||
|
|
||||||
|
if(!ww || !hh) {
|
||||||
|
container.appendChild(svg.make('path', Object.assign({
|
||||||
|
'd': (
|
||||||
|
'M ' + xL1 + ' ' + y1 +
|
||||||
|
' L ' + xR + ' ' + y1 +
|
||||||
|
' A ' + r + ' ' + r + ' 0 0 1 ' + xR + ' ' + y2 +
|
||||||
|
' L ' + xL2 + ' ' + y2
|
||||||
|
),
|
||||||
|
}, attrs)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const heights = makeWavyLineHeights(hh);
|
||||||
|
const dw = ww / heights.length;
|
||||||
|
let p = 0;
|
||||||
|
|
||||||
|
let points = '';
|
||||||
|
for(let x = xL1; x + dw <= xR; x += dw) {
|
||||||
|
points += (
|
||||||
|
x + ' ' +
|
||||||
|
(y1 + heights[(p ++) % heights.length]) + ' '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ym = (y1 + y2) / 2;
|
||||||
|
for(let t = 0; t + dw / r <= Math.PI; t += dw / r) {
|
||||||
|
const h = heights[(p ++) % heights.length];
|
||||||
|
points += (
|
||||||
|
(xR + Math.sin(t) * (r - h)) + ' ' +
|
||||||
|
(ym - Math.cos(t) * (r - h)) + ' '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let x = xR; x - dw >= xL2; x -= dw) {
|
||||||
|
points += (
|
||||||
|
x + ' ' +
|
||||||
|
(y2 - heights[(p ++) % heights.length]) + ' '
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
points += xL2 + ' ' + y2;
|
||||||
|
container.appendChild(svg.make('polyline', Object.assign({
|
||||||
|
points,
|
||||||
|
}, attrs)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CONNECTING_LINE = new ConnectingLine();
|
||||||
|
|
||||||
class Connect extends BaseComponent {
|
class Connect extends BaseComponent {
|
||||||
separation({label, agentNames, options}, env) {
|
separation({label, agentNames, options}, env) {
|
||||||
const config = env.theme.connect;
|
const config = env.theme.connect;
|
||||||
|
@ -179,16 +278,13 @@ define([
|
||||||
const y1 = y0 + r * 2;
|
const y1 = y0 + r * 2;
|
||||||
|
|
||||||
const lineAttrs = config.lineAttrs[options.line];
|
const lineAttrs = config.lineAttrs[options.line];
|
||||||
env.shapeLayer.appendChild(svg.make('path', Object.assign({
|
CONNECTING_LINE.renderRev(env.shapeLayer, {
|
||||||
'd': (
|
xL1: lineX + lArrow.lineGap(env.theme, lineAttrs),
|
||||||
'M ' + (lineX + lArrow.lineGap(env.theme, lineAttrs)) +
|
xL2: lineX + rArrow.lineGap(env.theme, lineAttrs),
|
||||||
' ' + y0 +
|
y1: y0,
|
||||||
' L ' + x1 + ' ' + y0 +
|
y2: y1,
|
||||||
' A ' + r + ' ' + r + ' 0 0 1 ' + x1 + ' ' + y1 +
|
xR: x1,
|
||||||
' L ' + (lineX + rArrow.lineGap(env.theme, lineAttrs)) +
|
}, lineAttrs);
|
||||||
' ' + y1
|
|
||||||
),
|
|
||||||
}, lineAttrs)));
|
|
||||||
|
|
||||||
lArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y0, dir: 1});
|
lArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y0, dir: 1});
|
||||||
rArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y1, dir: 1});
|
rArrow.render(env.shapeLayer, env.theme, {x: lineX, y: y1, dir: 1});
|
||||||
|
@ -241,12 +337,11 @@ define([
|
||||||
});
|
});
|
||||||
|
|
||||||
const lineAttrs = config.lineAttrs[options.line];
|
const lineAttrs = config.lineAttrs[options.line];
|
||||||
env.shapeLayer.appendChild(svg.make('line', Object.assign({
|
CONNECTING_LINE.renderFlat(env.shapeLayer, {
|
||||||
'x1': x0 + lArrow.lineGap(env.theme, lineAttrs) * dir,
|
x1: x0 + lArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||||
'y1': y,
|
x2: x1 - rArrow.lineGap(env.theme, lineAttrs) * dir,
|
||||||
'x2': x1 - rArrow.lineGap(env.theme, lineAttrs) * dir,
|
y,
|
||||||
'y2': y,
|
}, lineAttrs);
|
||||||
}, lineAttrs)));
|
|
||||||
|
|
||||||
lArrow.render(env.shapeLayer, env.theme, {x: x0, y, dir});
|
lArrow.render(env.shapeLayer, env.theme, {x: x0, y, dir});
|
||||||
rArrow.render(env.shapeLayer, env.theme, {x: x1, y, dir: -dir});
|
rArrow.render(env.shapeLayer, env.theme, {x: x1, y, dir: -dir});
|
||||||
|
|
|
@ -70,6 +70,15 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'stroke-dasharray': '4, 2',
|
'stroke-dasharray': '4, 2',
|
||||||
},
|
},
|
||||||
|
'wave': {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
'stroke-linejoin': 'round',
|
||||||
|
'stroke-linecap': 'round',
|
||||||
|
'wave-width': 6,
|
||||||
|
'wave-height': 0.5,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
arrow: {
|
arrow: {
|
||||||
single: {
|
single: {
|
||||||
|
|
|
@ -76,6 +76,15 @@ define(['core/ArrayUtilities', 'svg/SVGShapes'], (array, SVGShapes) => {
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'stroke-dasharray': '10, 4',
|
'stroke-dasharray': '10, 4',
|
||||||
},
|
},
|
||||||
|
'wave': {
|
||||||
|
'fill': 'none',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'stroke-linejoin': 'round',
|
||||||
|
'stroke-linecap': 'round',
|
||||||
|
'wave-width': 10,
|
||||||
|
'wave-height': 1,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
arrow: {
|
arrow: {
|
||||||
single: {
|
single: {
|
||||||
|
|
Loading…
Reference in New Issue