Add person indicator, add sketch rendering for databases [#36]
This commit is contained in:
parent
4551df9395
commit
a60d8fb0cb
|
@ -207,17 +207,52 @@
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDB(attrs, position) {
|
renderPerson({iconHeight, iconWidth}, iconAttrs, boxAttrs, position) {
|
||||||
const z = attrs['db-z'];
|
const cx = position.x + position.width / 2;
|
||||||
|
const sx = iconWidth / 2;
|
||||||
|
const sy = iconHeight;
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + iconHeight) +
|
||||||
|
'a' + sx + ' ' + (sy * 0.3) + ' 0 0 1' +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * 0.224) + ' 0' +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.1) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.275) +
|
||||||
|
's' + (-sx * 0.176) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * 0.35) +
|
||||||
|
's' + (-sx * 0.4) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * 0.35) +
|
||||||
|
's' + (sx * 0.176) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (-sy * 0.275)
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.box(boxAttrs, {
|
||||||
|
height: position.height - iconHeight,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + iconHeight,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB({tilt}, attrs, position) {
|
||||||
return this.svg.el('g').add(
|
return this.svg.el('g').add(
|
||||||
this.svg.box({
|
this.svg.box({
|
||||||
'rx': position.width / 2,
|
'rx': position.width / 2,
|
||||||
'ry': z,
|
'ry': tilt,
|
||||||
}, position).attrs(attrs),
|
}, position).attrs(attrs),
|
||||||
this.svg.el('path')
|
this.svg.el('path')
|
||||||
.attr('d', (
|
.attr('d', (
|
||||||
'M' + position.x + ' ' + (position.y + z) +
|
'M' + position.x + ' ' + (position.y + tilt) +
|
||||||
'a' + (position.width / 2) + ' ' + z +
|
'a' + (position.width / 2) + ' ' + tilt +
|
||||||
' 0 0 0 ' + position.width + ' 0'
|
' 0 0 0 ' + position.width + ' 0'
|
||||||
))
|
))
|
||||||
.attrs(attrs)
|
.attrs(attrs)
|
||||||
|
@ -527,6 +562,31 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -535,11 +595,10 @@
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 5}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 5,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
|
@ -912,6 +971,34 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'rx': 4,
|
||||||
|
'ry': 4,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT$1,
|
||||||
|
'font-weight': 'bold',
|
||||||
|
'font-size': 14,
|
||||||
|
'line-height': LINE_HEIGHT$1,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 4,
|
top: 4,
|
||||||
|
@ -920,11 +1007,10 @@
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
},
|
},
|
||||||
arrowBottom: 2 + 14 * 1.3 / 2,
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 2}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'db-z': 2,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$1,
|
'font-family': FONT$1,
|
||||||
|
@ -2899,6 +2985,31 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 4,
|
||||||
|
},
|
||||||
|
arrowBottom: 12,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 12,
|
||||||
|
iconWidth: 14,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT$2,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT$2,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 9,
|
top: 9,
|
||||||
|
@ -2907,11 +3018,10 @@
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 12,
|
arrowBottom: 12,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 4}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 4,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$2,
|
'font-family': FONT$2,
|
||||||
|
@ -3210,6 +3320,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const AGENT_INFO_TYPES = [
|
const AGENT_INFO_TYPES = [
|
||||||
|
'person',
|
||||||
'database',
|
'database',
|
||||||
'red',
|
'red',
|
||||||
];
|
];
|
||||||
|
@ -5183,21 +5294,23 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
class CapBox {
|
class CapBox {
|
||||||
getConfig(options, env) {
|
getConfig(options, env, isBegin) {
|
||||||
let config = null;
|
let config = null;
|
||||||
if(options.includes('database')) {
|
if(options.includes('database')) {
|
||||||
config = env.theme.agentCap.database;
|
config = env.theme.agentCap.database;
|
||||||
|
} else if(isBegin && options.includes('person')) {
|
||||||
|
config = env.theme.agentCap.person;
|
||||||
}
|
}
|
||||||
return config || env.theme.agentCap.box;
|
return config || env.theme.agentCap.box;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareMeasurements({formattedLabel, options}, env) {
|
prepareMeasurements({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
separation({formattedLabel, options}, env) {
|
separation({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const width = (
|
const width = (
|
||||||
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
||||||
config.padding.left +
|
config.padding.left +
|
||||||
|
@ -5211,8 +5324,8 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
topShift({formattedLabel, options}, env) {
|
topShift({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const height = (
|
const height = (
|
||||||
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
||||||
config.padding.top +
|
config.padding.top +
|
||||||
|
@ -5221,8 +5334,8 @@
|
||||||
return Math.max(0, height - config.arrowBottom);
|
return Math.max(0, height - config.arrowBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(y, {x, formattedLabel, options}, env) {
|
render(y, {x, formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
|
|
||||||
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
||||||
|
|
||||||
|
@ -9091,6 +9204,22 @@
|
||||||
},
|
},
|
||||||
boxRenderer: this.renderBox.bind(this),
|
boxRenderer: this.renderBox.bind(this),
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT_FAMILY,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT$3,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
boxRenderer: this.renderPerson.bind(this),
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -9099,10 +9228,7 @@
|
||||||
bottom: 2,
|
bottom: 2,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, Object.assign({
|
boxRenderer: this.renderDB.bind(this),
|
||||||
'fill': '#FFFFFF',
|
|
||||||
'db-z': 5,
|
|
||||||
}, PENCIL.normal)),
|
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$3,
|
'font-family': FONT$3,
|
||||||
'font-size': 12,
|
'font-size': 12,
|
||||||
|
@ -9414,6 +9540,99 @@
|
||||||
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPerson(position) {
|
||||||
|
const sx = 18 / 2;
|
||||||
|
const sy = 15;
|
||||||
|
const iconAttrs = Object.assign({'fill': 'none'}, PENCIL.normal);
|
||||||
|
const cx = position.x + position.width / 2;
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
const lean = v(0.1, 0.05 * this.handedness);
|
||||||
|
const skew = v(0.1, 0.05 * this.handedness);
|
||||||
|
const shoulders = v(0.05, 0.35);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + sy) +
|
||||||
|
'c' + (sx * lean) + ' ' + (-sy * (shoulders - skew)) +
|
||||||
|
' ' + (sx * (2 + lean)) + ' ' + (-sy * (shoulders + skew)) +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * v(0.05, 0.224)) + ' ' + v(0.02, 0) +
|
||||||
|
' ' + (sx * v(0.07, 0.4)) + ' ' + (sy * v(0.02, 0.1)) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * v(0.05, 0.275)) +
|
||||||
|
's' + (-sx * v(0.05, 0.176)) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * v(0.05, 0.35)) +
|
||||||
|
's' + (-sx * v(0.07, 0.4)) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * v(0.05, 0.35)) +
|
||||||
|
's' + (sx * v(0.05, 0.176)) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * v(0.05, 0.4)) + ' ' + (-sy * v(0.02, 0.275))
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.renderBox({
|
||||||
|
height: position.height - sy,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + sy,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB(pos) {
|
||||||
|
const tilt = 5;
|
||||||
|
const tiltC = tilt * 1.2;
|
||||||
|
|
||||||
|
const l1 = this.lineNodes(
|
||||||
|
{x: pos.x, y: pos.y + tilt},
|
||||||
|
{x: pos.x, y: pos.y + pos.height - tilt},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const l2 = this.lineNodes(
|
||||||
|
{x: pos.x + pos.width, y: pos.y + pos.height - tilt},
|
||||||
|
{x: pos.x + pos.width, y: pos.y + tilt},
|
||||||
|
{move: false}
|
||||||
|
);
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
|
||||||
|
const cx = pos.x + pos.width / 2;
|
||||||
|
const dx = -pos.width * this.handedness / 2;
|
||||||
|
const topX1 = cx - dx * v(0.03, 1.02);
|
||||||
|
const topY1 = pos.y + tilt * v(0.15, 1);
|
||||||
|
const topX2 = cx + dx * v(0.03, 1.02);
|
||||||
|
const topY2 = pos.y + tilt * v(0.15, 1);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
l1.nodes +
|
||||||
|
'C' + l1.p2.x + ' ' + (l1.p2.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + (l2.p1.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + l2.p1.y +
|
||||||
|
l2.nodes
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF'),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + topX1 + ' ' + topY1 +
|
||||||
|
'C' + (topX1 + dx * 0.2) + ' ' + (topY1 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + (topY2 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + topY2 +
|
||||||
|
'S' + topX1 + ' ' + (topY1 + v(0.2, tiltC)) +
|
||||||
|
' ' + v(1, topX1) + ' ' + v(0.5, topY1)
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderNote({x, y, width, height}) {
|
renderNote({x, y, width, height}) {
|
||||||
const flickSize = 5;
|
const flickSize = 5;
|
||||||
const lT = this.lineNodes(
|
const lT = this.lineNodes(
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -207,17 +207,52 @@
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDB(attrs, position) {
|
renderPerson({iconHeight, iconWidth}, iconAttrs, boxAttrs, position) {
|
||||||
const z = attrs['db-z'];
|
const cx = position.x + position.width / 2;
|
||||||
|
const sx = iconWidth / 2;
|
||||||
|
const sy = iconHeight;
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + iconHeight) +
|
||||||
|
'a' + sx + ' ' + (sy * 0.3) + ' 0 0 1' +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * 0.224) + ' 0' +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.1) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.275) +
|
||||||
|
's' + (-sx * 0.176) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * 0.35) +
|
||||||
|
's' + (-sx * 0.4) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * 0.35) +
|
||||||
|
's' + (sx * 0.176) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (-sy * 0.275)
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.box(boxAttrs, {
|
||||||
|
height: position.height - iconHeight,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + iconHeight,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB({tilt}, attrs, position) {
|
||||||
return this.svg.el('g').add(
|
return this.svg.el('g').add(
|
||||||
this.svg.box({
|
this.svg.box({
|
||||||
'rx': position.width / 2,
|
'rx': position.width / 2,
|
||||||
'ry': z,
|
'ry': tilt,
|
||||||
}, position).attrs(attrs),
|
}, position).attrs(attrs),
|
||||||
this.svg.el('path')
|
this.svg.el('path')
|
||||||
.attr('d', (
|
.attr('d', (
|
||||||
'M' + position.x + ' ' + (position.y + z) +
|
'M' + position.x + ' ' + (position.y + tilt) +
|
||||||
'a' + (position.width / 2) + ' ' + z +
|
'a' + (position.width / 2) + ' ' + tilt +
|
||||||
' 0 0 0 ' + position.width + ' 0'
|
' 0 0 0 ' + position.width + ' 0'
|
||||||
))
|
))
|
||||||
.attrs(attrs)
|
.attrs(attrs)
|
||||||
|
@ -527,6 +562,31 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -535,11 +595,10 @@
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 5}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 5,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
|
@ -912,6 +971,34 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'rx': 4,
|
||||||
|
'ry': 4,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT$1,
|
||||||
|
'font-weight': 'bold',
|
||||||
|
'font-size': 14,
|
||||||
|
'line-height': LINE_HEIGHT$1,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 4,
|
top: 4,
|
||||||
|
@ -920,11 +1007,10 @@
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
},
|
},
|
||||||
arrowBottom: 2 + 14 * 1.3 / 2,
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 2}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'db-z': 2,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$1,
|
'font-family': FONT$1,
|
||||||
|
@ -2899,6 +2985,31 @@
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 4,
|
||||||
|
},
|
||||||
|
arrowBottom: 12,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 12,
|
||||||
|
iconWidth: 14,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT$2,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT$2,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 9,
|
top: 9,
|
||||||
|
@ -2907,11 +3018,10 @@
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 12,
|
arrowBottom: 12,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 4}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 4,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$2,
|
'font-family': FONT$2,
|
||||||
|
@ -3210,6 +3320,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const AGENT_INFO_TYPES = [
|
const AGENT_INFO_TYPES = [
|
||||||
|
'person',
|
||||||
'database',
|
'database',
|
||||||
'red',
|
'red',
|
||||||
];
|
];
|
||||||
|
@ -5183,21 +5294,23 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
class CapBox {
|
class CapBox {
|
||||||
getConfig(options, env) {
|
getConfig(options, env, isBegin) {
|
||||||
let config = null;
|
let config = null;
|
||||||
if(options.includes('database')) {
|
if(options.includes('database')) {
|
||||||
config = env.theme.agentCap.database;
|
config = env.theme.agentCap.database;
|
||||||
|
} else if(isBegin && options.includes('person')) {
|
||||||
|
config = env.theme.agentCap.person;
|
||||||
}
|
}
|
||||||
return config || env.theme.agentCap.box;
|
return config || env.theme.agentCap.box;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareMeasurements({formattedLabel, options}, env) {
|
prepareMeasurements({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
separation({formattedLabel, options}, env) {
|
separation({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const width = (
|
const width = (
|
||||||
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
||||||
config.padding.left +
|
config.padding.left +
|
||||||
|
@ -5211,8 +5324,8 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
topShift({formattedLabel, options}, env) {
|
topShift({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const height = (
|
const height = (
|
||||||
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
||||||
config.padding.top +
|
config.padding.top +
|
||||||
|
@ -5221,8 +5334,8 @@
|
||||||
return Math.max(0, height - config.arrowBottom);
|
return Math.max(0, height - config.arrowBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(y, {x, formattedLabel, options}, env) {
|
render(y, {x, formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
|
|
||||||
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
||||||
|
|
||||||
|
@ -9091,6 +9204,22 @@
|
||||||
},
|
},
|
||||||
boxRenderer: this.renderBox.bind(this),
|
boxRenderer: this.renderBox.bind(this),
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT_FAMILY,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT$3,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
boxRenderer: this.renderPerson.bind(this),
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -9099,10 +9228,7 @@
|
||||||
bottom: 2,
|
bottom: 2,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, Object.assign({
|
boxRenderer: this.renderDB.bind(this),
|
||||||
'fill': '#FFFFFF',
|
|
||||||
'db-z': 5,
|
|
||||||
}, PENCIL.normal)),
|
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT$3,
|
'font-family': FONT$3,
|
||||||
'font-size': 12,
|
'font-size': 12,
|
||||||
|
@ -9414,6 +9540,99 @@
|
||||||
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPerson(position) {
|
||||||
|
const sx = 18 / 2;
|
||||||
|
const sy = 15;
|
||||||
|
const iconAttrs = Object.assign({'fill': 'none'}, PENCIL.normal);
|
||||||
|
const cx = position.x + position.width / 2;
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
const lean = v(0.1, 0.05 * this.handedness);
|
||||||
|
const skew = v(0.1, 0.05 * this.handedness);
|
||||||
|
const shoulders = v(0.05, 0.35);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + sy) +
|
||||||
|
'c' + (sx * lean) + ' ' + (-sy * (shoulders - skew)) +
|
||||||
|
' ' + (sx * (2 + lean)) + ' ' + (-sy * (shoulders + skew)) +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * v(0.05, 0.224)) + ' ' + v(0.02, 0) +
|
||||||
|
' ' + (sx * v(0.07, 0.4)) + ' ' + (sy * v(0.02, 0.1)) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * v(0.05, 0.275)) +
|
||||||
|
's' + (-sx * v(0.05, 0.176)) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * v(0.05, 0.35)) +
|
||||||
|
's' + (-sx * v(0.07, 0.4)) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * v(0.05, 0.35)) +
|
||||||
|
's' + (sx * v(0.05, 0.176)) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * v(0.05, 0.4)) + ' ' + (-sy * v(0.02, 0.275))
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.renderBox({
|
||||||
|
height: position.height - sy,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + sy,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB(pos) {
|
||||||
|
const tilt = 5;
|
||||||
|
const tiltC = tilt * 1.2;
|
||||||
|
|
||||||
|
const l1 = this.lineNodes(
|
||||||
|
{x: pos.x, y: pos.y + tilt},
|
||||||
|
{x: pos.x, y: pos.y + pos.height - tilt},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const l2 = this.lineNodes(
|
||||||
|
{x: pos.x + pos.width, y: pos.y + pos.height - tilt},
|
||||||
|
{x: pos.x + pos.width, y: pos.y + tilt},
|
||||||
|
{move: false}
|
||||||
|
);
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
|
||||||
|
const cx = pos.x + pos.width / 2;
|
||||||
|
const dx = -pos.width * this.handedness / 2;
|
||||||
|
const topX1 = cx - dx * v(0.03, 1.02);
|
||||||
|
const topY1 = pos.y + tilt * v(0.15, 1);
|
||||||
|
const topX2 = cx + dx * v(0.03, 1.02);
|
||||||
|
const topY2 = pos.y + tilt * v(0.15, 1);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
l1.nodes +
|
||||||
|
'C' + l1.p2.x + ' ' + (l1.p2.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + (l2.p1.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + l2.p1.y +
|
||||||
|
l2.nodes
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF'),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + topX1 + ' ' + topY1 +
|
||||||
|
'C' + (topX1 + dx * 0.2) + ' ' + (topY1 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + (topY2 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + topY2 +
|
||||||
|
'S' + topX1 + ' ' + (topY1 + v(0.2, tiltC)) +
|
||||||
|
' ' + v(1, topX1) + ' ' + v(0.5, topY1)
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderNote({x, y, width, height}) {
|
renderNote({x, y, width, height}) {
|
||||||
const flickSize = 5;
|
const flickSize = 5;
|
||||||
const lT = this.lineNodes(
|
const lT = this.lineNodes(
|
||||||
|
|
|
@ -30,6 +30,7 @@ function suggestionsEqual(a, b) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AGENT_INFO_TYPES = [
|
const AGENT_INFO_TYPES = [
|
||||||
|
'person',
|
||||||
'database',
|
'database',
|
||||||
'red',
|
'red',
|
||||||
];
|
];
|
||||||
|
|
|
@ -712,6 +712,7 @@ describe('Code Mirror Mode', () => {
|
||||||
cm.getDoc().setValue('A is a ');
|
cm.getDoc().setValue('A is a ');
|
||||||
const hints = getHintTexts({ch: 7, line: 0});
|
const hints = getHintTexts({ch: 7, line: 0});
|
||||||
|
|
||||||
|
expect(hints).toContain('person ');
|
||||||
expect(hints).toContain('database ');
|
expect(hints).toContain('database ');
|
||||||
expect(hints).toContain('red ');
|
expect(hints).toContain('red ');
|
||||||
expect(hints).not.toContain('\n');
|
expect(hints).not.toContain('\n');
|
||||||
|
|
|
@ -7,21 +7,23 @@ const OUTLINE_ATTRS = {
|
||||||
};
|
};
|
||||||
|
|
||||||
class CapBox {
|
class CapBox {
|
||||||
getConfig(options, env) {
|
getConfig(options, env, isBegin) {
|
||||||
let config = null;
|
let config = null;
|
||||||
if(options.includes('database')) {
|
if(options.includes('database')) {
|
||||||
config = env.theme.agentCap.database;
|
config = env.theme.agentCap.database;
|
||||||
|
} else if(isBegin && options.includes('person')) {
|
||||||
|
config = env.theme.agentCap.person;
|
||||||
}
|
}
|
||||||
return config || env.theme.agentCap.box;
|
return config || env.theme.agentCap.box;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareMeasurements({formattedLabel, options}, env) {
|
prepareMeasurements({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
env.textSizer.expectMeasure(config.labelAttrs, formattedLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
separation({formattedLabel, options}, env) {
|
separation({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const width = (
|
const width = (
|
||||||
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
env.textSizer.measure(config.labelAttrs, formattedLabel).width +
|
||||||
config.padding.left +
|
config.padding.left +
|
||||||
|
@ -35,8 +37,8 @@ class CapBox {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
topShift({formattedLabel, options}, env) {
|
topShift({formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
const height = (
|
const height = (
|
||||||
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
env.textSizer.measureHeight(config.labelAttrs, formattedLabel) +
|
||||||
config.padding.top +
|
config.padding.top +
|
||||||
|
@ -45,8 +47,8 @@ class CapBox {
|
||||||
return Math.max(0, height - config.arrowBottom);
|
return Math.max(0, height - config.arrowBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(y, {x, formattedLabel, options}, env) {
|
render(y, {x, formattedLabel, options}, env, isBegin) {
|
||||||
const config = this.getConfig(options, env);
|
const config = this.getConfig(options, env, isBegin);
|
||||||
|
|
||||||
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
const text = env.svg.boxedText(config, formattedLabel, {x, y});
|
||||||
|
|
||||||
|
|
|
@ -204,17 +204,52 @@ export default class BaseTheme {
|
||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDB(attrs, position) {
|
renderPerson({iconHeight, iconWidth}, iconAttrs, boxAttrs, position) {
|
||||||
const z = attrs['db-z'];
|
const cx = position.x + position.width / 2;
|
||||||
|
const sx = iconWidth / 2;
|
||||||
|
const sy = iconHeight;
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + iconHeight) +
|
||||||
|
'a' + sx + ' ' + (sy * 0.3) + ' 0 0 1' +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * 0.224) + ' 0' +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.1) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * 0.275) +
|
||||||
|
's' + (-sx * 0.176) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * 0.35) +
|
||||||
|
's' + (-sx * 0.4) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * 0.35) +
|
||||||
|
's' + (sx * 0.176) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (-sy * 0.275)
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.box(boxAttrs, {
|
||||||
|
height: position.height - iconHeight,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + iconHeight,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB({tilt}, attrs, position) {
|
||||||
return this.svg.el('g').add(
|
return this.svg.el('g').add(
|
||||||
this.svg.box({
|
this.svg.box({
|
||||||
'rx': position.width / 2,
|
'rx': position.width / 2,
|
||||||
'ry': z,
|
'ry': tilt,
|
||||||
}, position).attrs(attrs),
|
}, position).attrs(attrs),
|
||||||
this.svg.el('path')
|
this.svg.el('path')
|
||||||
.attr('d', (
|
.attr('d', (
|
||||||
'M' + position.x + ' ' + (position.y + z) +
|
'M' + position.x + ' ' + (position.y + tilt) +
|
||||||
'a' + (position.width / 2) + ' ' + z +
|
'a' + (position.width / 2) + ' ' + tilt +
|
||||||
' 0 0 0 ' + position.width + ' 0'
|
' 0 0 0 ' + position.width + ' 0'
|
||||||
))
|
))
|
||||||
.attrs(attrs)
|
.attrs(attrs)
|
||||||
|
|
|
@ -99,6 +99,31 @@ export default class BasicTheme extends BaseTheme {
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -107,11 +132,10 @@ export default class BasicTheme extends BaseTheme {
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 5}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 5,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
|
|
|
@ -102,6 +102,34 @@ export default class ChunkyTheme extends BaseTheme {
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 3,
|
||||||
|
right: 3,
|
||||||
|
bottom: 1,
|
||||||
|
},
|
||||||
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 15,
|
||||||
|
iconWidth: 18,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 3,
|
||||||
|
'rx': 4,
|
||||||
|
'ry': 4,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT,
|
||||||
|
'font-weight': 'bold',
|
||||||
|
'font-size': 14,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 4,
|
top: 4,
|
||||||
|
@ -110,11 +138,10 @@ export default class ChunkyTheme extends BaseTheme {
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
},
|
},
|
||||||
arrowBottom: 2 + 14 * 1.3 / 2,
|
arrowBottom: 2 + 14 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 2}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 3,
|
'stroke-width': 3,
|
||||||
'db-z': 2,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
|
|
|
@ -99,6 +99,31 @@ export default class MonospaceTheme extends BaseTheme {
|
||||||
'text-anchor': 'middle',
|
'text-anchor': 'middle',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 16,
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 4,
|
||||||
|
},
|
||||||
|
arrowBottom: 12,
|
||||||
|
boxRenderer: this.renderPerson.bind(this, {
|
||||||
|
iconHeight: 12,
|
||||||
|
iconWidth: 14,
|
||||||
|
}, {
|
||||||
|
'fill': '#000000',
|
||||||
|
}, {
|
||||||
|
'fill': '#FFFFFF',
|
||||||
|
'stroke': '#000000',
|
||||||
|
'stroke-width': 1,
|
||||||
|
}),
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 9,
|
top: 9,
|
||||||
|
@ -107,11 +132,10 @@ export default class MonospaceTheme extends BaseTheme {
|
||||||
bottom: 3,
|
bottom: 3,
|
||||||
},
|
},
|
||||||
arrowBottom: 12,
|
arrowBottom: 12,
|
||||||
boxRenderer: this.renderDB.bind(this, {
|
boxRenderer: this.renderDB.bind(this, {tilt: 4}, {
|
||||||
'fill': '#FFFFFF',
|
'fill': '#FFFFFF',
|
||||||
'stroke': '#000000',
|
'stroke': '#000000',
|
||||||
'stroke-width': 1,
|
'stroke-width': 1,
|
||||||
'db-z': 4,
|
|
||||||
}),
|
}),
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
|
|
|
@ -145,6 +145,22 @@ export default class SketchTheme extends BaseTheme {
|
||||||
},
|
},
|
||||||
boxRenderer: this.renderBox.bind(this),
|
boxRenderer: this.renderBox.bind(this),
|
||||||
},
|
},
|
||||||
|
person: {
|
||||||
|
padding: {
|
||||||
|
top: 20,
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
bottom: 5,
|
||||||
|
},
|
||||||
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
|
labelAttrs: {
|
||||||
|
'font-family': FONT_FAMILY,
|
||||||
|
'font-size': 12,
|
||||||
|
'line-height': LINE_HEIGHT,
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
},
|
||||||
|
boxRenderer: this.renderPerson.bind(this),
|
||||||
|
},
|
||||||
database: {
|
database: {
|
||||||
padding: {
|
padding: {
|
||||||
top: 12,
|
top: 12,
|
||||||
|
@ -153,10 +169,7 @@ export default class SketchTheme extends BaseTheme {
|
||||||
bottom: 2,
|
bottom: 2,
|
||||||
},
|
},
|
||||||
arrowBottom: 5 + 12 * 1.3 / 2,
|
arrowBottom: 5 + 12 * 1.3 / 2,
|
||||||
boxRenderer: this.renderDB.bind(this, Object.assign({
|
boxRenderer: this.renderDB.bind(this),
|
||||||
'fill': '#FFFFFF',
|
|
||||||
'db-z': 5,
|
|
||||||
}, PENCIL.normal)),
|
|
||||||
labelAttrs: {
|
labelAttrs: {
|
||||||
'font-family': FONT,
|
'font-family': FONT,
|
||||||
'font-size': 12,
|
'font-size': 12,
|
||||||
|
@ -468,6 +481,99 @@ export default class SketchTheme extends BaseTheme {
|
||||||
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
.attrs(attrs || (thick ? PENCIL.thick : PENCIL.normal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPerson(position) {
|
||||||
|
const sx = 18 / 2;
|
||||||
|
const sy = 15;
|
||||||
|
const iconAttrs = Object.assign({'fill': 'none'}, PENCIL.normal);
|
||||||
|
const cx = position.x + position.width / 2;
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
const lean = v(0.1, 0.05 * this.handedness);
|
||||||
|
const skew = v(0.1, 0.05 * this.handedness);
|
||||||
|
const shoulders = v(0.05, 0.35);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + (cx - sx) + ' ' + (position.y + sy) +
|
||||||
|
'c' + (sx * lean) + ' ' + (-sy * (shoulders - skew)) +
|
||||||
|
' ' + (sx * (2 + lean)) + ' ' + (-sy * (shoulders + skew)) +
|
||||||
|
' ' + (sx * 2) + ' 0'
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + cx + ' ' + position.y +
|
||||||
|
'c' + (sx * v(0.05, 0.224)) + ' ' + v(0.02, 0) +
|
||||||
|
' ' + (sx * v(0.07, 0.4)) + ' ' + (sy * v(0.02, 0.1)) +
|
||||||
|
' ' + (sx * 0.4) + ' ' + (sy * v(0.05, 0.275)) +
|
||||||
|
's' + (-sx * v(0.05, 0.176)) + ' ' + (sy * 0.35) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (sy * v(0.05, 0.35)) +
|
||||||
|
's' + (-sx * v(0.07, 0.4)) + ' ' + (-sy * 0.175) +
|
||||||
|
' ' + (-sx * 0.4) + ' ' + (-sy * v(0.05, 0.35)) +
|
||||||
|
's' + (sx * v(0.05, 0.176)) + ' ' + (-sy * 0.275) +
|
||||||
|
' ' + (sx * v(0.05, 0.4)) + ' ' + (-sy * v(0.02, 0.275))
|
||||||
|
))
|
||||||
|
.attrs(iconAttrs),
|
||||||
|
this.renderBox({
|
||||||
|
height: position.height - sy,
|
||||||
|
width: position.width,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y + sy,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDB(pos) {
|
||||||
|
const tilt = 5;
|
||||||
|
const tiltC = tilt * 1.2;
|
||||||
|
|
||||||
|
const l1 = this.lineNodes(
|
||||||
|
{x: pos.x, y: pos.y + tilt},
|
||||||
|
{x: pos.x, y: pos.y + pos.height - tilt},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const l2 = this.lineNodes(
|
||||||
|
{x: pos.x + pos.width, y: pos.y + pos.height - tilt},
|
||||||
|
{x: pos.x + pos.width, y: pos.y + tilt},
|
||||||
|
{move: false}
|
||||||
|
);
|
||||||
|
|
||||||
|
const v = this.vary.bind(this);
|
||||||
|
|
||||||
|
const cx = pos.x + pos.width / 2;
|
||||||
|
const dx = -pos.width * this.handedness / 2;
|
||||||
|
const topX1 = cx - dx * v(0.03, 1.02);
|
||||||
|
const topY1 = pos.y + tilt * v(0.15, 1);
|
||||||
|
const topX2 = cx + dx * v(0.03, 1.02);
|
||||||
|
const topY2 = pos.y + tilt * v(0.15, 1);
|
||||||
|
|
||||||
|
return this.svg.el('g').add(
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
l1.nodes +
|
||||||
|
'C' + l1.p2.x + ' ' + (l1.p2.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + (l2.p1.y + v(0.1, tiltC)) +
|
||||||
|
' ' + l2.p1.x + ' ' + l2.p1.y +
|
||||||
|
l2.nodes
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF'),
|
||||||
|
this.svg.el('path')
|
||||||
|
.attr('d', (
|
||||||
|
'M' + topX1 + ' ' + topY1 +
|
||||||
|
'C' + (topX1 + dx * 0.2) + ' ' + (topY1 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + (topY2 - v(0.2, tiltC)) +
|
||||||
|
' ' + topX2 + ' ' + topY2 +
|
||||||
|
'S' + topX1 + ' ' + (topY1 + v(0.2, tiltC)) +
|
||||||
|
' ' + v(1, topX1) + ' ' + v(0.5, topY1)
|
||||||
|
))
|
||||||
|
.attrs(PENCIL.normal)
|
||||||
|
.attr('fill', '#FFFFFF')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderNote({x, y, width, height}) {
|
renderNote({x, y, width, height}) {
|
||||||
const flickSize = 5;
|
const flickSize = 5;
|
||||||
const lT = this.lineNodes(
|
const lT = this.lineNodes(
|
||||||
|
|
|
@ -305,6 +305,11 @@
|
||||||
preview: 'headers box\nA is red\nbegin A',
|
preview: 'headers box\nA is red\nbegin A',
|
||||||
title: 'Red agent line',
|
title: 'Red agent line',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: '{Agent} is a person',
|
||||||
|
preview: 'headers box\nA is a person\nbegin A',
|
||||||
|
title: 'Person indicator',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: '{Agent} is a database',
|
code: '{Agent} is a database',
|
||||||
preview: 'headers box\nA is a database\nbegin A',
|
preview: 'headers box\nA is a database\nbegin A',
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -302,6 +302,11 @@ export default [
|
||||||
preview: 'headers box\nA is red\nbegin A',
|
preview: 'headers box\nA is red\nbegin A',
|
||||||
title: 'Red agent line',
|
title: 'Red agent line',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
code: '{Agent} is a person',
|
||||||
|
preview: 'headers box\nA is a person\nbegin A',
|
||||||
|
title: 'Person indicator',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
code: '{Agent} is a database',
|
code: '{Agent} is a database',
|
||||||
preview: 'headers box\nA is a database\nbegin A',
|
preview: 'headers box\nA is a database\nbegin A',
|
||||||
|
|
Loading…
Reference in New Issue