Adding Loop rendering component
This commit is contained in:
parent
c1716570a8
commit
f4e7bc0e76
@ -4,11 +4,11 @@ import {
|
||||
tan,
|
||||
grey,
|
||||
blue,
|
||||
fontFamily,
|
||||
fontSizeSmall,
|
||||
strokeBase
|
||||
strokeBase,
|
||||
infoText
|
||||
} from 'rendering/style';
|
||||
|
||||
export { infoText };
|
||||
export const literal = {
|
||||
fill: blue,
|
||||
strokeWidth: '1px',
|
||||
@ -31,7 +31,3 @@ export const capture = {
|
||||
export const anchor = {
|
||||
fill: brown
|
||||
};
|
||||
export const infoText = {
|
||||
fontSize: fontSizeSmall,
|
||||
fontFamily
|
||||
};
|
||||
|
133
src/rendering/Loop/index.js
Normal file
133
src/rendering/Loop/index.js
Normal file
@ -0,0 +1,133 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { getBBox } from 'layout';
|
||||
|
||||
import * as style from 'rendering/style';
|
||||
|
||||
const radius = 10;
|
||||
const arrowSize = 5;
|
||||
|
||||
const Loop = ({
|
||||
label,
|
||||
labelTransform,
|
||||
contentTransform,
|
||||
loopPaths,
|
||||
children
|
||||
}) => {
|
||||
const labelProps = {
|
||||
transform: labelTransform,
|
||||
style: style.infoText
|
||||
};
|
||||
|
||||
return <>
|
||||
<path style={ style.connectors } d={ loopPaths }/>
|
||||
{ label && <text { ...labelProps }>{ label }</text> }
|
||||
<g transform={ contentTransform }>
|
||||
{ children }
|
||||
</g>
|
||||
</>;
|
||||
};
|
||||
|
||||
Loop.propTypes = {
|
||||
label: PropTypes.string,
|
||||
greedy: PropTypes.bool,
|
||||
skip: PropTypes.bool,
|
||||
repeat: PropTypes.bool,
|
||||
labelTransform: PropTypes.string,
|
||||
contentTransform: PropTypes.string,
|
||||
loopPaths: PropTypes.string,
|
||||
children: PropTypes.node.isRequired
|
||||
};
|
||||
|
||||
const generateOffsetBox = (box, { skip, repeat }) => {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
|
||||
if (skip) {
|
||||
x = 1.5 * radius;
|
||||
y = radius;
|
||||
} else if (repeat) {
|
||||
x = radius;
|
||||
}
|
||||
|
||||
return {
|
||||
...box,
|
||||
x, y,
|
||||
axisX1: x + box.axisX1,
|
||||
axisX2: x + box.axisX2,
|
||||
axisY: y + box.axisY
|
||||
};
|
||||
};
|
||||
const skipPath = (box, greedy) => {
|
||||
const vert = Math.max(0, box.axisY - box.y - radius);
|
||||
const horiz = box.width - radius;
|
||||
|
||||
return `
|
||||
M 0,${ box.axisY }
|
||||
q ${ radius },0 ${ radius },${ -radius }
|
||||
v ${ -vert }
|
||||
q 0,${ -radius } ${ radius },${ -radius }
|
||||
h ${ horiz }
|
||||
q ${ radius },0 ${ radius },${ radius }
|
||||
v ${ vert }
|
||||
q 0,${ radius } ${ radius },${ radius }
|
||||
` + (greedy ? '' : `
|
||||
M ${ radius },${ box.axisY - 1.5 * radius }
|
||||
l ${ arrowSize },${ arrowSize }
|
||||
z
|
||||
l ${ -arrowSize },${ arrowSize }
|
||||
`);
|
||||
};
|
||||
const repeatPath = (box, greedy) => {
|
||||
const vert = box.y + box.height - box.axisY - radius;
|
||||
|
||||
return `
|
||||
M ${ box.x },${ box.axisY }
|
||||
q ${ -radius },0 ${ -radius },${ radius }
|
||||
v ${ vert }
|
||||
q 0,${ radius } ${ radius },${ radius }
|
||||
h ${ box.width }
|
||||
q ${ radius },0 ${ radius },${ -radius }
|
||||
v ${ -vert }
|
||||
q 0,${ -radius } ${ -radius },${ -radius }
|
||||
` + (greedy ? `
|
||||
m ${ radius },${ 1.5 * radius }
|
||||
l ${ arrowSize },${ -arrowSize }
|
||||
z
|
||||
l ${ -arrowSize },${ -arrowSize }
|
||||
` : '');
|
||||
};
|
||||
const layout = data => {
|
||||
const { label, greedy, skip, repeat } = data.props || {};
|
||||
const childBox = generateOffsetBox(data.children[0].box, { skip, repeat });
|
||||
const labelBox = label ?
|
||||
getBBox(<text style={ style.infoText }>{ label }</text>) :
|
||||
{ width: 0, height: 0 };
|
||||
const width = childBox.width + childBox.x * 2;
|
||||
const height = childBox.height + labelBox.height +
|
||||
(skip ? 10 : 0) + (repeat ? 10 : 0);
|
||||
|
||||
data.box = {
|
||||
width,
|
||||
height,
|
||||
axisY: childBox.axisY,
|
||||
axisX1: childBox.axisX1,
|
||||
axisX2: childBox.axisX2
|
||||
};
|
||||
|
||||
data.props = {
|
||||
...data.props,
|
||||
labelTransform: `translate(${ width - labelBox.width } ${ height })`,
|
||||
contentTransform: `translate(${ childBox.x } ${ childBox.y })`,
|
||||
loopPaths: [
|
||||
skip && skipPath(childBox, greedy),
|
||||
repeat && repeatPath(childBox, greedy)
|
||||
].filter(Boolean).join('')
|
||||
};
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export default Loop;
|
||||
export { layout };
|
@ -23,3 +23,8 @@ export const connectors = {
|
||||
fillOpacity: 0,
|
||||
...strokeBase
|
||||
};
|
||||
|
||||
export const infoText = {
|
||||
fontSize: fontSizeSmall,
|
||||
fontFamily
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ import * as SVG from 'rendering/SVG';
|
||||
import * as Pin from 'rendering/Pin';
|
||||
import * as Text from 'rendering/Text';
|
||||
import * as Box from 'rendering/Box';
|
||||
import * as Loop from 'rendering/Loop';
|
||||
import * as HorizontalLayout from 'rendering/HorizontalLayout';
|
||||
import * as VerticalLayout from 'rendering/VerticalLayout';
|
||||
|
||||
@ -10,6 +11,7 @@ export default {
|
||||
Pin,
|
||||
Text,
|
||||
Box,
|
||||
Loop,
|
||||
HorizontalLayout,
|
||||
VerticalLayout
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user