Add support for faded connectors
This commit is contained in:
parent
b25c5dafb4
commit
e85890563c
|
@ -81,9 +81,12 @@ function findSamples(content) {
|
||||||
* code: (
|
* code: (
|
||||||
* 'theme chunky\n' +
|
* 'theme chunky\n' +
|
||||||
* 'define ABC as A, DEF as B\n' +
|
* 'define ABC as A, DEF as B\n' +
|
||||||
|
* 'A is red\n' +
|
||||||
|
* 'B is blue\n' +
|
||||||
* 'A -> B\n' +
|
* 'A -> B\n' +
|
||||||
* 'B -> ]\n' +
|
* 'B -~ ]\n' +
|
||||||
* '] -> B\n' +
|
* 'divider space with height 0\n' +
|
||||||
|
* '] ~-> B\n' +
|
||||||
* 'B -> A\n' +
|
* 'B -> A\n' +
|
||||||
* 'terminators fade'
|
* 'terminators fade'
|
||||||
* ),
|
* ),
|
||||||
|
|
|
@ -598,6 +598,10 @@
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 16,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 7,
|
short: 7,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
@ -985,6 +989,10 @@
|
||||||
'stroke-linecap': 'round',
|
'stroke-linecap': 'round',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 3,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 10,
|
short: 10,
|
||||||
radius: 5,
|
radius: 5,
|
||||||
|
@ -2960,6 +2968,10 @@
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 10,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 8,
|
short: 8,
|
||||||
radius: 4,
|
radius: 4,
|
||||||
|
@ -4424,6 +4436,7 @@
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '<', type: 1},
|
{tok: '<', type: 1},
|
||||||
{tok: '<<', type: 2},
|
{tok: '<<', type: 2},
|
||||||
|
{tok: '~', type: 3},
|
||||||
];
|
];
|
||||||
const mTypes = [
|
const mTypes = [
|
||||||
{tok: '-', type: 'solid'},
|
{tok: '-', type: 'solid'},
|
||||||
|
@ -4434,19 +4447,27 @@
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '>', type: 1},
|
{tok: '>', type: 1},
|
||||||
{tok: '>>', type: 2},
|
{tok: '>>', type: 2},
|
||||||
{tok: 'x', type: 3},
|
{tok: '~', type: 3},
|
||||||
|
{tok: 'x', type: 4},
|
||||||
];
|
];
|
||||||
const arrows = (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) => {
|
combine([lTypes, mTypes, rTypes]).forEach((arrow) => {
|
||||||
|
const [left, line, right] = arrow;
|
||||||
|
if(left.type === 0 && right.type === 0) {
|
||||||
|
// A line without arrows cannot be a connector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(left.type === 3 && line.type === 'wave' && right.type === 0) {
|
||||||
|
// ~~ could be fade-wave-none or none-wave-fade
|
||||||
|
// We allow only none-wave-fade to resolve this
|
||||||
|
return;
|
||||||
|
}
|
||||||
types.set(arrow.map((part) => part.tok).join(''), {
|
types.set(arrow.map((part) => part.tok).join(''), {
|
||||||
left: arrow[0].type,
|
left: left.type,
|
||||||
line: arrow[1].type,
|
line: line.type,
|
||||||
right: arrow[2].type,
|
right: right.type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5776,6 +5797,18 @@
|
||||||
'fill': 'transparent',
|
'fill': 'transparent',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MASK_PAD = 5;
|
||||||
|
|
||||||
|
function applyMask(shape, maskShapes, env, bounds) {
|
||||||
|
if(!maskShapes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mask = env.svg.el('mask')
|
||||||
|
.attr('maskUnits', 'userSpaceOnUse')
|
||||||
|
.add(env.svg.box({'fill': '#FFFFFF'}, bounds), ...maskShapes);
|
||||||
|
shape.attr('mask', 'url(#' + env.addDef(mask) + ')');
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowhead {
|
class Arrowhead {
|
||||||
constructor(propName) {
|
constructor(propName) {
|
||||||
this.propName = propName;
|
this.propName = propName;
|
||||||
|
@ -5800,9 +5833,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
const short = this.short(theme);
|
const short = this.short(env.theme);
|
||||||
layer.add(config.render(config.attrs, {
|
layer.add(config.render(config.attrs, {
|
||||||
dir,
|
dir,
|
||||||
height: config.height,
|
height: config.height,
|
||||||
|
@ -5834,13 +5867,58 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Arrowfade {
|
||||||
|
getConfig(theme) {
|
||||||
|
return theme.connect.arrow.fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
render({lineMask}, env, pt, dir) {
|
||||||
|
const config = this.getConfig(env.theme);
|
||||||
|
const {short, size} = config;
|
||||||
|
let fadeID = null;
|
||||||
|
const delta = MASK_PAD / (size + MASK_PAD * 2);
|
||||||
|
if(dir.dx >= 0) {
|
||||||
|
fadeID = env.addDef('arrowFadeL', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#000000'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
]));
|
||||||
|
} else {
|
||||||
|
fadeID = env.addDef('arrowFadeR', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#000000'},
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
const p1 = {x: pt.x + dir.dx * short, y: pt.y + dir.dy * short};
|
||||||
|
const p2 = {x: p1.x + dir.dx * size, y: p1.y + dir.dy * size};
|
||||||
|
const box = env.svg.box({'fill': 'url(#' + fadeID + ')'}, {
|
||||||
|
height: Math.abs(p1.y - p2.y) + MASK_PAD * 2,
|
||||||
|
width: size + MASK_PAD * 2,
|
||||||
|
x: Math.min(p1.x, p2.x) - MASK_PAD,
|
||||||
|
y: Math.min(p1.y, p2.y) - MASK_PAD,
|
||||||
|
});
|
||||||
|
lineMask.push(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
width(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
|
||||||
|
height() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineGap(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowcross {
|
class Arrowcross {
|
||||||
getConfig(theme) {
|
getConfig(theme) {
|
||||||
return theme.connect.arrow.cross;
|
return theme.connect.arrow.cross;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
layer.add(config.render({
|
layer.add(config.render({
|
||||||
radius: config.radius,
|
radius: config.radius,
|
||||||
x: pt.x + config.short * dir.dx,
|
x: pt.x + config.short * dir.dx,
|
||||||
|
@ -5871,6 +5949,7 @@
|
||||||
},
|
},
|
||||||
new Arrowhead('single'),
|
new Arrowhead('single'),
|
||||||
new Arrowhead('double'),
|
new Arrowhead('double'),
|
||||||
|
new Arrowfade(),
|
||||||
new Arrowcross(),
|
new Arrowcross(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -5950,8 +6029,9 @@
|
||||||
|
|
||||||
const dx1 = lArrow.lineGap(env.theme, line);
|
const dx1 = lArrow.lineGap(env.theme, line);
|
||||||
const dx2 = rArrow.lineGap(env.theme, line);
|
const dx2 = rArrow.lineGap(env.theme, line);
|
||||||
|
const rad = env.theme.connect.loopbackRadius;
|
||||||
const rendered = line.renderRev({
|
const rendered = line.renderRev({
|
||||||
rad: env.theme.connect.loopbackRadius,
|
rad,
|
||||||
x1: x1 + dx1,
|
x1: x1 + dx1,
|
||||||
x2: x2 + dx2,
|
x2: x2 + dx2,
|
||||||
xR,
|
xR,
|
||||||
|
@ -5960,15 +6040,24 @@
|
||||||
});
|
});
|
||||||
clickable.add(rendered.shape);
|
clickable.add(rendered.shape);
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, {
|
const lineMask = [];
|
||||||
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p1.x - dx1,
|
x: rendered.p1.x - dx1,
|
||||||
y: rendered.p1.y,
|
y: rendered.p1.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
rArrow.render(clickable, env.theme, {
|
rArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p2.x - dx2,
|
x: rendered.p2.x - dx2,
|
||||||
y: rendered.p2.y,
|
y: rendered.p2.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: y2 - y1 + MASK_PAD * 2,
|
||||||
|
width: xR + rad - Math.min(x1, x2) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: y1 - MASK_PAD,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
||||||
|
@ -6066,8 +6155,20 @@
|
||||||
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
||||||
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, p1, {dx, dy});
|
const lineMask = [];
|
||||||
rArrow.render(clickable, env.theme, p2, {dx: -dx, dy: -dy});
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, p1, {dx, dy});
|
||||||
|
rArrow.render({layer: clickable, lineMask}, env, p2, {
|
||||||
|
dx: -dx,
|
||||||
|
dy: -dy,
|
||||||
|
});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: Math.abs(y2 - y1) + MASK_PAD * 2,
|
||||||
|
width: Math.abs(x2 - x1) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: Math.min(y1, y2) - MASK_PAD,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lArrow,
|
lArrow,
|
||||||
|
@ -9044,6 +9145,10 @@
|
||||||
}, PENCIL.normal),
|
}, PENCIL.normal),
|
||||||
render: this.renderArrowHead.bind(this),
|
render: this.renderArrowHead.bind(this),
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 0,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 5,
|
short: 5,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -598,6 +598,10 @@
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 16,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 7,
|
short: 7,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
@ -985,6 +989,10 @@
|
||||||
'stroke-linecap': 'round',
|
'stroke-linecap': 'round',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 3,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 10,
|
short: 10,
|
||||||
radius: 5,
|
radius: 5,
|
||||||
|
@ -2960,6 +2968,10 @@
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 10,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 8,
|
short: 8,
|
||||||
radius: 4,
|
radius: 4,
|
||||||
|
@ -4424,6 +4436,7 @@
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '<', type: 1},
|
{tok: '<', type: 1},
|
||||||
{tok: '<<', type: 2},
|
{tok: '<<', type: 2},
|
||||||
|
{tok: '~', type: 3},
|
||||||
];
|
];
|
||||||
const mTypes = [
|
const mTypes = [
|
||||||
{tok: '-', type: 'solid'},
|
{tok: '-', type: 'solid'},
|
||||||
|
@ -4434,19 +4447,27 @@
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '>', type: 1},
|
{tok: '>', type: 1},
|
||||||
{tok: '>>', type: 2},
|
{tok: '>>', type: 2},
|
||||||
{tok: 'x', type: 3},
|
{tok: '~', type: 3},
|
||||||
|
{tok: 'x', type: 4},
|
||||||
];
|
];
|
||||||
const arrows = (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) => {
|
combine([lTypes, mTypes, rTypes]).forEach((arrow) => {
|
||||||
|
const [left, line, right] = arrow;
|
||||||
|
if(left.type === 0 && right.type === 0) {
|
||||||
|
// A line without arrows cannot be a connector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(left.type === 3 && line.type === 'wave' && right.type === 0) {
|
||||||
|
// ~~ could be fade-wave-none or none-wave-fade
|
||||||
|
// We allow only none-wave-fade to resolve this
|
||||||
|
return;
|
||||||
|
}
|
||||||
types.set(arrow.map((part) => part.tok).join(''), {
|
types.set(arrow.map((part) => part.tok).join(''), {
|
||||||
left: arrow[0].type,
|
left: left.type,
|
||||||
line: arrow[1].type,
|
line: line.type,
|
||||||
right: arrow[2].type,
|
right: right.type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5776,6 +5797,18 @@
|
||||||
'fill': 'transparent',
|
'fill': 'transparent',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MASK_PAD = 5;
|
||||||
|
|
||||||
|
function applyMask(shape, maskShapes, env, bounds) {
|
||||||
|
if(!maskShapes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mask = env.svg.el('mask')
|
||||||
|
.attr('maskUnits', 'userSpaceOnUse')
|
||||||
|
.add(env.svg.box({'fill': '#FFFFFF'}, bounds), ...maskShapes);
|
||||||
|
shape.attr('mask', 'url(#' + env.addDef(mask) + ')');
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowhead {
|
class Arrowhead {
|
||||||
constructor(propName) {
|
constructor(propName) {
|
||||||
this.propName = propName;
|
this.propName = propName;
|
||||||
|
@ -5800,9 +5833,9 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
const short = this.short(theme);
|
const short = this.short(env.theme);
|
||||||
layer.add(config.render(config.attrs, {
|
layer.add(config.render(config.attrs, {
|
||||||
dir,
|
dir,
|
||||||
height: config.height,
|
height: config.height,
|
||||||
|
@ -5834,13 +5867,58 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Arrowfade {
|
||||||
|
getConfig(theme) {
|
||||||
|
return theme.connect.arrow.fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
render({lineMask}, env, pt, dir) {
|
||||||
|
const config = this.getConfig(env.theme);
|
||||||
|
const {short, size} = config;
|
||||||
|
let fadeID = null;
|
||||||
|
const delta = MASK_PAD / (size + MASK_PAD * 2);
|
||||||
|
if(dir.dx >= 0) {
|
||||||
|
fadeID = env.addDef('arrowFadeL', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#000000'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
]));
|
||||||
|
} else {
|
||||||
|
fadeID = env.addDef('arrowFadeR', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#000000'},
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
const p1 = {x: pt.x + dir.dx * short, y: pt.y + dir.dy * short};
|
||||||
|
const p2 = {x: p1.x + dir.dx * size, y: p1.y + dir.dy * size};
|
||||||
|
const box = env.svg.box({'fill': 'url(#' + fadeID + ')'}, {
|
||||||
|
height: Math.abs(p1.y - p2.y) + MASK_PAD * 2,
|
||||||
|
width: size + MASK_PAD * 2,
|
||||||
|
x: Math.min(p1.x, p2.x) - MASK_PAD,
|
||||||
|
y: Math.min(p1.y, p2.y) - MASK_PAD,
|
||||||
|
});
|
||||||
|
lineMask.push(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
width(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
|
||||||
|
height() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineGap(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowcross {
|
class Arrowcross {
|
||||||
getConfig(theme) {
|
getConfig(theme) {
|
||||||
return theme.connect.arrow.cross;
|
return theme.connect.arrow.cross;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
layer.add(config.render({
|
layer.add(config.render({
|
||||||
radius: config.radius,
|
radius: config.radius,
|
||||||
x: pt.x + config.short * dir.dx,
|
x: pt.x + config.short * dir.dx,
|
||||||
|
@ -5871,6 +5949,7 @@
|
||||||
},
|
},
|
||||||
new Arrowhead('single'),
|
new Arrowhead('single'),
|
||||||
new Arrowhead('double'),
|
new Arrowhead('double'),
|
||||||
|
new Arrowfade(),
|
||||||
new Arrowcross(),
|
new Arrowcross(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -5950,8 +6029,9 @@
|
||||||
|
|
||||||
const dx1 = lArrow.lineGap(env.theme, line);
|
const dx1 = lArrow.lineGap(env.theme, line);
|
||||||
const dx2 = rArrow.lineGap(env.theme, line);
|
const dx2 = rArrow.lineGap(env.theme, line);
|
||||||
|
const rad = env.theme.connect.loopbackRadius;
|
||||||
const rendered = line.renderRev({
|
const rendered = line.renderRev({
|
||||||
rad: env.theme.connect.loopbackRadius,
|
rad,
|
||||||
x1: x1 + dx1,
|
x1: x1 + dx1,
|
||||||
x2: x2 + dx2,
|
x2: x2 + dx2,
|
||||||
xR,
|
xR,
|
||||||
|
@ -5960,15 +6040,24 @@
|
||||||
});
|
});
|
||||||
clickable.add(rendered.shape);
|
clickable.add(rendered.shape);
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, {
|
const lineMask = [];
|
||||||
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p1.x - dx1,
|
x: rendered.p1.x - dx1,
|
||||||
y: rendered.p1.y,
|
y: rendered.p1.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
rArrow.render(clickable, env.theme, {
|
rArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p2.x - dx2,
|
x: rendered.p2.x - dx2,
|
||||||
y: rendered.p2.y,
|
y: rendered.p2.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: y2 - y1 + MASK_PAD * 2,
|
||||||
|
width: xR + rad - Math.min(x1, x2) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: y1 - MASK_PAD,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
||||||
|
@ -6066,8 +6155,20 @@
|
||||||
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
||||||
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, p1, {dx, dy});
|
const lineMask = [];
|
||||||
rArrow.render(clickable, env.theme, p2, {dx: -dx, dy: -dy});
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, p1, {dx, dy});
|
||||||
|
rArrow.render({layer: clickable, lineMask}, env, p2, {
|
||||||
|
dx: -dx,
|
||||||
|
dy: -dy,
|
||||||
|
});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: Math.abs(y2 - y1) + MASK_PAD * 2,
|
||||||
|
width: Math.abs(x2 - x1) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: Math.min(y1, y2) - MASK_PAD,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lArrow,
|
lArrow,
|
||||||
|
@ -9044,6 +9145,10 @@
|
||||||
}, PENCIL.normal),
|
}, PENCIL.normal),
|
||||||
render: this.renderArrowHead.bind(this),
|
render: this.renderArrowHead.bind(this),
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 0,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 5,
|
short: 5,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
|
|
@ -42,6 +42,7 @@ const CONNECT = {
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '<', type: 1},
|
{tok: '<', type: 1},
|
||||||
{tok: '<<', type: 2},
|
{tok: '<<', type: 2},
|
||||||
|
{tok: '~', type: 3},
|
||||||
];
|
];
|
||||||
const mTypes = [
|
const mTypes = [
|
||||||
{tok: '-', type: 'solid'},
|
{tok: '-', type: 'solid'},
|
||||||
|
@ -52,19 +53,27 @@ const CONNECT = {
|
||||||
{tok: '', type: 0},
|
{tok: '', type: 0},
|
||||||
{tok: '>', type: 1},
|
{tok: '>', type: 1},
|
||||||
{tok: '>>', type: 2},
|
{tok: '>>', type: 2},
|
||||||
{tok: 'x', type: 3},
|
{tok: '~', type: 3},
|
||||||
|
{tok: 'x', type: 4},
|
||||||
];
|
];
|
||||||
const arrows = (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) => {
|
combine([lTypes, mTypes, rTypes]).forEach((arrow) => {
|
||||||
|
const [left, line, right] = arrow;
|
||||||
|
if(left.type === 0 && right.type === 0) {
|
||||||
|
// A line without arrows cannot be a connector
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(left.type === 3 && line.type === 'wave' && right.type === 0) {
|
||||||
|
// ~~ could be fade-wave-none or none-wave-fade
|
||||||
|
// We allow only none-wave-fade to resolve this
|
||||||
|
return;
|
||||||
|
}
|
||||||
types.set(arrow.map((part) => part.tok).join(''), {
|
types.set(arrow.map((part) => part.tok).join(''), {
|
||||||
left: arrow[0].type,
|
left: left.type,
|
||||||
line: arrow[1].type,
|
line: line.type,
|
||||||
right: arrow[2].type,
|
right: right.type,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -453,31 +453,62 @@ describe('Sequence Parser', () => {
|
||||||
const parsed = parser.parse(
|
const parsed = parser.parse(
|
||||||
'A->B\n' +
|
'A->B\n' +
|
||||||
'A->>B\n' +
|
'A->>B\n' +
|
||||||
|
'A-~B\n' +
|
||||||
|
'A-xB\n' +
|
||||||
'A<-B\n' +
|
'A<-B\n' +
|
||||||
'A<->B\n' +
|
'A<->B\n' +
|
||||||
'A<->>B\n' +
|
'A<->>B\n' +
|
||||||
|
'A<-~B\n' +
|
||||||
|
'A<-xB\n' +
|
||||||
'A<<-B\n' +
|
'A<<-B\n' +
|
||||||
'A<<->B\n' +
|
'A<<->B\n' +
|
||||||
'A<<->>B\n' +
|
'A<<->>B\n' +
|
||||||
'A-xB\n' +
|
'A<<-~B\n' +
|
||||||
|
'A<<-xB\n' +
|
||||||
|
'A~-B\n' +
|
||||||
|
'A~->B\n' +
|
||||||
|
'A~->>B\n' +
|
||||||
|
'A~-~B\n' +
|
||||||
|
'A~-xB\n' +
|
||||||
|
|
||||||
'A-->B\n' +
|
'A-->B\n' +
|
||||||
'A-->>B\n' +
|
'A-->>B\n' +
|
||||||
|
'A--~B\n' +
|
||||||
|
'A--xB\n' +
|
||||||
'A<--B\n' +
|
'A<--B\n' +
|
||||||
'A<-->B\n' +
|
'A<-->B\n' +
|
||||||
'A<-->>B\n' +
|
'A<-->>B\n' +
|
||||||
|
'A<--~B\n' +
|
||||||
|
'A<--xB\n' +
|
||||||
'A<<--B\n' +
|
'A<<--B\n' +
|
||||||
'A<<-->B\n' +
|
'A<<-->B\n' +
|
||||||
'A<<-->>B\n' +
|
'A<<-->>B\n' +
|
||||||
'A--xB\n' +
|
'A<<--~B\n' +
|
||||||
|
'A<<--xB\n' +
|
||||||
|
'A~--B\n' +
|
||||||
|
'A~-->B\n' +
|
||||||
|
'A~-->>B\n' +
|
||||||
|
'A~--~B\n' +
|
||||||
|
'A~--xB\n' +
|
||||||
|
|
||||||
'A~>B\n' +
|
'A~>B\n' +
|
||||||
'A~>>B\n' +
|
'A~>>B\n' +
|
||||||
|
'A~~B\n' +
|
||||||
|
'A~xB\n' +
|
||||||
'A<~B\n' +
|
'A<~B\n' +
|
||||||
'A<~>B\n' +
|
'A<~>B\n' +
|
||||||
'A<~>>B\n' +
|
'A<~>>B\n' +
|
||||||
|
'A<~~B\n' +
|
||||||
|
'A<~xB\n' +
|
||||||
'A<<~B\n' +
|
'A<<~B\n' +
|
||||||
'A<<~>B\n' +
|
'A<<~>B\n' +
|
||||||
'A<<~>>B\n' +
|
'A<<~>>B\n' +
|
||||||
'A~xB\n'
|
'A<<~~B\n' +
|
||||||
|
'A<<~xB\n' +
|
||||||
|
'A~~>B\n' +
|
||||||
|
'A~~>>B\n' +
|
||||||
|
'A~~~B\n' +
|
||||||
|
'A~~xB\n'
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(parsed.stages).toEqual([
|
expect(parsed.stages).toEqual([
|
||||||
|
@ -488,31 +519,62 @@ describe('Sequence Parser', () => {
|
||||||
right: 1,
|
right: 1,
|
||||||
}),
|
}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'solid', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 0, line: 'solid', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'solid', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'solid', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'solid', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 2}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'solid', right: 3}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 2, line: 'solid', right: 4}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'solid', right: 0}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'solid', right: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'solid', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'solid', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'solid', right: 4}),
|
||||||
|
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'dash', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 2}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'dash', right: 3}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 2, line: 'dash', right: 4}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'dash', right: 0}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'dash', right: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'dash', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'dash', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'dash', right: 4}),
|
||||||
|
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 1, line: 'wave', right: 4}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 0}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 0}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 1}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 1}),
|
||||||
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 2}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 2}),
|
||||||
PARSED.connect(['A', 'B'], {left: 0, line: 'wave', right: 3}),
|
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 2, line: 'wave', right: 4}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'wave', right: 1}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'wave', right: 2}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'wave', right: 3}),
|
||||||
|
PARSED.connect(['A', 'B'], {left: 3, line: 'wave', right: 4}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,18 @@ const OUTLINE_ATTRS = {
|
||||||
'fill': 'transparent',
|
'fill': 'transparent',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const MASK_PAD = 5;
|
||||||
|
|
||||||
|
function applyMask(shape, maskShapes, env, bounds) {
|
||||||
|
if(!maskShapes.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const mask = env.svg.el('mask')
|
||||||
|
.attr('maskUnits', 'userSpaceOnUse')
|
||||||
|
.add(env.svg.box({'fill': '#FFFFFF'}, bounds), ...maskShapes);
|
||||||
|
shape.attr('mask', 'url(#' + env.addDef(mask) + ')');
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowhead {
|
class Arrowhead {
|
||||||
constructor(propName) {
|
constructor(propName) {
|
||||||
this.propName = propName;
|
this.propName = propName;
|
||||||
|
@ -30,9 +42,9 @@ class Arrowhead {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
const short = this.short(theme);
|
const short = this.short(env.theme);
|
||||||
layer.add(config.render(config.attrs, {
|
layer.add(config.render(config.attrs, {
|
||||||
dir,
|
dir,
|
||||||
height: config.height,
|
height: config.height,
|
||||||
|
@ -64,13 +76,58 @@ class Arrowhead {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Arrowfade {
|
||||||
|
getConfig(theme) {
|
||||||
|
return theme.connect.arrow.fade;
|
||||||
|
}
|
||||||
|
|
||||||
|
render({lineMask}, env, pt, dir) {
|
||||||
|
const config = this.getConfig(env.theme);
|
||||||
|
const {short, size} = config;
|
||||||
|
let fadeID = null;
|
||||||
|
const delta = MASK_PAD / (size + MASK_PAD * 2);
|
||||||
|
if(dir.dx >= 0) {
|
||||||
|
fadeID = env.addDef('arrowFadeL', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#000000'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
]));
|
||||||
|
} else {
|
||||||
|
fadeID = env.addDef('arrowFadeR', () => env.svg.linearGradient({}, [
|
||||||
|
{'offset': delta * 100 + '%', 'stop-color': '#FFFFFF'},
|
||||||
|
{'offset': (100 - delta * 100) + '%', 'stop-color': '#000000'},
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
const p1 = {x: pt.x + dir.dx * short, y: pt.y + dir.dy * short};
|
||||||
|
const p2 = {x: p1.x + dir.dx * size, y: p1.y + dir.dy * size};
|
||||||
|
const box = env.svg.box({'fill': 'url(#' + fadeID + ')'}, {
|
||||||
|
height: Math.abs(p1.y - p2.y) + MASK_PAD * 2,
|
||||||
|
width: size + MASK_PAD * 2,
|
||||||
|
x: Math.min(p1.x, p2.x) - MASK_PAD,
|
||||||
|
y: Math.min(p1.y, p2.y) - MASK_PAD,
|
||||||
|
});
|
||||||
|
lineMask.push(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
width(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
|
||||||
|
height() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lineGap(theme) {
|
||||||
|
return this.getConfig(theme).short;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Arrowcross {
|
class Arrowcross {
|
||||||
getConfig(theme) {
|
getConfig(theme) {
|
||||||
return theme.connect.arrow.cross;
|
return theme.connect.arrow.cross;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(layer, theme, pt, dir) {
|
render({layer}, env, pt, dir) {
|
||||||
const config = this.getConfig(theme);
|
const config = this.getConfig(env.theme);
|
||||||
layer.add(config.render({
|
layer.add(config.render({
|
||||||
radius: config.radius,
|
radius: config.radius,
|
||||||
x: pt.x + config.short * dir.dx,
|
x: pt.x + config.short * dir.dx,
|
||||||
|
@ -101,6 +158,7 @@ const ARROWHEADS = [
|
||||||
},
|
},
|
||||||
new Arrowhead('single'),
|
new Arrowhead('single'),
|
||||||
new Arrowhead('double'),
|
new Arrowhead('double'),
|
||||||
|
new Arrowfade(),
|
||||||
new Arrowcross(),
|
new Arrowcross(),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -180,8 +238,9 @@ export class Connect extends BaseComponent {
|
||||||
|
|
||||||
const dx1 = lArrow.lineGap(env.theme, line);
|
const dx1 = lArrow.lineGap(env.theme, line);
|
||||||
const dx2 = rArrow.lineGap(env.theme, line);
|
const dx2 = rArrow.lineGap(env.theme, line);
|
||||||
|
const rad = env.theme.connect.loopbackRadius;
|
||||||
const rendered = line.renderRev({
|
const rendered = line.renderRev({
|
||||||
rad: env.theme.connect.loopbackRadius,
|
rad,
|
||||||
x1: x1 + dx1,
|
x1: x1 + dx1,
|
||||||
x2: x2 + dx2,
|
x2: x2 + dx2,
|
||||||
xR,
|
xR,
|
||||||
|
@ -190,15 +249,24 @@ export class Connect extends BaseComponent {
|
||||||
});
|
});
|
||||||
clickable.add(rendered.shape);
|
clickable.add(rendered.shape);
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, {
|
const lineMask = [];
|
||||||
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p1.x - dx1,
|
x: rendered.p1.x - dx1,
|
||||||
y: rendered.p1.y,
|
y: rendered.p1.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
rArrow.render(clickable, env.theme, {
|
rArrow.render({layer: clickable, lineMask}, env, {
|
||||||
x: rendered.p2.x - dx2,
|
x: rendered.p2.x - dx2,
|
||||||
y: rendered.p2.y,
|
y: rendered.p2.y,
|
||||||
}, {dx: 1, dy: 0});
|
}, {dx: 1, dy: 0});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: y2 - y1 + MASK_PAD * 2,
|
||||||
|
width: xR + rad - Math.min(x1, x2) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: y1 - MASK_PAD,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
renderSelfConnect({label, agentIDs, options}, env, from, yBegin) {
|
||||||
|
@ -296,8 +364,20 @@ export class Connect extends BaseComponent {
|
||||||
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
const p1 = {x: rendered.p1.x - d1 * dx, y: rendered.p1.y - d1 * dy};
|
||||||
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
const p2 = {x: rendered.p2.x + d2 * dx, y: rendered.p2.y + d2 * dy};
|
||||||
|
|
||||||
lArrow.render(clickable, env.theme, p1, {dx, dy});
|
const lineMask = [];
|
||||||
rArrow.render(clickable, env.theme, p2, {dx: -dx, dy: -dy});
|
|
||||||
|
lArrow.render({layer: clickable, lineMask}, env, p1, {dx, dy});
|
||||||
|
rArrow.render({layer: clickable, lineMask}, env, p2, {
|
||||||
|
dx: -dx,
|
||||||
|
dy: -dy,
|
||||||
|
});
|
||||||
|
|
||||||
|
applyMask(rendered.shape, lineMask, env, {
|
||||||
|
height: Math.abs(y2 - y1) + MASK_PAD * 2,
|
||||||
|
width: Math.abs(x2 - x1) + MASK_PAD * 2,
|
||||||
|
x: Math.min(x1, x2) - MASK_PAD,
|
||||||
|
y: Math.min(y1, y2) - MASK_PAD,
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lArrow,
|
lArrow,
|
||||||
|
|
|
@ -170,6 +170,10 @@ export default class BasicTheme extends BaseTheme {
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 16,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 7,
|
short: 7,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
|
|
@ -179,6 +179,10 @@ export default class ChunkyTheme extends BaseTheme {
|
||||||
'stroke-linecap': 'round',
|
'stroke-linecap': 'round',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 3,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 10,
|
short: 10,
|
||||||
radius: 5,
|
radius: 5,
|
||||||
|
|
|
@ -170,6 +170,10 @@ export default class MonospaceTheme extends BaseTheme {
|
||||||
'stroke-linejoin': 'miter',
|
'stroke-linejoin': 'miter',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 2,
|
||||||
|
size: 10,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 8,
|
short: 8,
|
||||||
radius: 4,
|
radius: 4,
|
||||||
|
|
|
@ -201,6 +201,10 @@ export default class SketchTheme extends BaseTheme {
|
||||||
}, PENCIL.normal),
|
}, PENCIL.normal),
|
||||||
render: this.renderArrowHead.bind(this),
|
render: this.renderArrowHead.bind(this),
|
||||||
},
|
},
|
||||||
|
'fade': {
|
||||||
|
short: 0,
|
||||||
|
size: 12,
|
||||||
|
},
|
||||||
'cross': {
|
'cross': {
|
||||||
short: 5,
|
short: 5,
|
||||||
radius: 3,
|
radius: 3,
|
||||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 13 KiB |
|
@ -1,14 +1,15 @@
|
||||||
export default [
|
export default [
|
||||||
'Connect.svg',
|
'AgentOptions.svg',
|
||||||
'SelfConnect.svg',
|
|
||||||
'Divider.svg',
|
|
||||||
'DividerMasking.svg',
|
|
||||||
'Asynchronous.svg',
|
'Asynchronous.svg',
|
||||||
'Block.svg',
|
'Block.svg',
|
||||||
'CollapsedBlocks.svg',
|
'CollapsedBlocks.svg',
|
||||||
|
'Connect.svg',
|
||||||
|
'Divider.svg',
|
||||||
|
'DividerMasking.svg',
|
||||||
|
'Fade.svg',
|
||||||
|
'Markdown.svg',
|
||||||
|
'Parallel.svg',
|
||||||
'Reference.svg',
|
'Reference.svg',
|
||||||
'ReferenceLayering.svg',
|
'ReferenceLayering.svg',
|
||||||
'Markdown.svg',
|
'SelfConnect.svg',
|
||||||
'AgentOptions.svg',
|
|
||||||
'Parallel.svg',
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -200,6 +200,10 @@
|
||||||
code: '[ -> {Agent1}: {Message1}\n{Agent1} -> ]: {Message2}',
|
code: '[ -> {Agent1}: {Message1}\n{Agent1} -> ]: {Message2}',
|
||||||
title: 'Arrows to/from the sides',
|
title: 'Arrows to/from the sides',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: '{Agent1} -~ ]: {Message1}\n{Agent1} <-~ ]: {Message2}',
|
||||||
|
title: 'Fading arrows',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: 'text right: {Message}',
|
code: 'text right: {Message}',
|
||||||
preview: (
|
preview: (
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -197,6 +197,10 @@ export default [
|
||||||
code: '[ -> {Agent1}: {Message1}\n{Agent1} -> ]: {Message2}',
|
code: '[ -> {Agent1}: {Message1}\n{Agent1} -> ]: {Message2}',
|
||||||
title: 'Arrows to/from the sides',
|
title: 'Arrows to/from the sides',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: '{Agent1} -~ ]: {Message1}\n{Agent1} <-~ ]: {Message2}',
|
||||||
|
title: 'Fading arrows',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: 'text right: {Message}',
|
code: 'text right: {Message}',
|
||||||
preview: (
|
preview: (
|
||||||
|
|
Loading…
Reference in New Issue