Adding promisified setState and simplfying reflow code for SVG stuff

This commit is contained in:
Jeff Avallone 2018-02-17 12:06:35 -05:00
parent e04e4edc1f
commit f364673388
8 changed files with 103 additions and 117 deletions

View File

@ -6,7 +6,13 @@ class Base extends React.PureComponent {
return this.tempBBox ? this.tempBBox : (this.state || {}).bbox; return this.tempBBox ? this.tempBBox : (this.state || {}).bbox;
} }
setBBox(box, recalculate = {}) { setStateAsync(state) {
return new Promise(resolve => {
this.setState(state, resolve);
});
}
async setBBox(box, recalculate = {}) {
let bbox = this._currentBBox() || Map({ width: 0, height: 0}); let bbox = this._currentBBox() || Map({ width: 0, height: 0});
bbox = bbox.merge(box); bbox = bbox.merge(box);
@ -24,9 +30,8 @@ class Base extends React.PureComponent {
} }
this.tempBBox = bbox; // Want to get the updated bbox while setState is pending this.tempBBox = bbox; // Want to get the updated bbox while setState is pending
this.setState({ bbox }, () => { await this.setStateAsync({ bbox });
this.tempBBox = null; this.tempBBox = null;
});
} }
getBBox() { getBBox() {

View File

@ -16,26 +16,24 @@ class Box extends Base {
} }
reflow() { reflow() {
return new Promise(resolve => { const { padding, useAnchors } = this.props;
const { padding, useAnchors } = this.props; const box = this.contained.getBBox();
const box = this.contained.getBBox(); const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0};
const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0};
this.setBBox({ this.setBBox({
width: Math.max(box.width + 2 * padding, labelBox.width), width: Math.max(box.width + 2 * padding, labelBox.width),
height: box.height + 2 * padding + labelBox.height, height: box.height + 2 * padding + labelBox.height,
axisY: (useAnchors ? box.axisY : box.height / 2) + padding + labelBox.height, axisY: (useAnchors ? box.axisY : box.height / 2) + padding + labelBox.height,
axisX1: useAnchors ? box.axisX1 + padding : 0, axisX1: useAnchors ? box.axisX1 + padding : 0,
axisX2: useAnchors ? box.axisX2 + padding : box.width + 2 * padding axisX2: useAnchors ? box.axisX2 + padding : box.width + 2 * padding
}); });
this.setState({ return this.setStateAsync({
width: this.getBBox().width, width: this.getBBox().width,
height: box.height + 2 * padding, height: box.height + 2 * padding,
contentTransform: `translate(${ padding } ${ padding + labelBox.height })`, contentTransform: `translate(${ padding } ${ padding + labelBox.height })`,
rectTransform: `translate(0 ${ labelBox.height })`, rectTransform: `translate(0 ${ labelBox.height })`,
labelTransform: `translate(0 ${ labelBox.height })` labelTransform: `translate(0 ${ labelBox.height })`
}, resolve);
}); });
} }

View File

@ -50,27 +50,25 @@ class HorizontalLayout extends Base {
return; return;
} }
return new Promise(resolve => { const { spacing, withConnectors } = this.props;
const { spacing, withConnectors } = this.props;
const childBoxes = this.children.map(child => child.getBBox()); const childBoxes = this.children.map(child => child.getBBox());
const verticalCenter = childBoxes.reduce((center, box) => Math.max(center, box.axisY), 0); const verticalCenter = childBoxes.reduce((center, box) => Math.max(center, box.axisY), 0);
const width = childBoxes.reduce((width, box) => width + box.width, 0) + (childBoxes.length - 1) * spacing; const width = childBoxes.reduce((width, box) => width + box.width, 0) + (childBoxes.length - 1) * spacing;
const height = childBoxes.reduce((ascHeight, box) => Math.max(ascHeight, box.axisY), 0) + const height = childBoxes.reduce((ascHeight, box) => Math.max(ascHeight, box.axisY), 0) +
childBoxes.reduce((decHeight, box) => Math.max(decHeight, box.height - box.axisY), 0); childBoxes.reduce((decHeight, box) => Math.max(decHeight, box.height - box.axisY), 0);
this.setBBox({ width, height, axisY: verticalCenter }, { axisX1: true, axisX2: true }); this.setBBox({ width, height, axisY: verticalCenter }, { axisX1: true, axisX2: true });
let offset = 0; let offset = 0;
childBoxes.forEach(box => { childBoxes.forEach(box => {
box.offsetX = offset; box.offsetX = offset;
box.offsetY = this.getBBox().axisY - box.axisY; box.offsetY = this.getBBox().axisY - box.axisY;
offset += box.width + spacing; offset += box.width + spacing;
}); });
this.setState({ this.setStateAsync({
childTransforms: this.updateChildTransforms(childBoxes), childTransforms: this.updateChildTransforms(childBoxes),
connectorPaths: withConnectors ? this.updateConnectorPaths(childBoxes) : '' connectorPaths: withConnectors ? this.updateConnectorPaths(childBoxes) : ''
}, resolve);
}); });
} }

View File

@ -37,14 +37,12 @@ class Image extends Base {
} }
reflow() { reflow() {
return new Promise(resolve => { const { padding } = this.props;
const { padding } = this.props; const box = this.contained.getBBox();
const box = this.contained.getBBox();
this.setState({ return this.setStateAsync({
width: Math.round(box.width + 2 * padding), width: Math.round(box.width + 2 * padding),
height: Math.round(box.height + 2 * padding) height: Math.round(box.height + 2 * padding)
}, resolve);
}); });
} }

View File

@ -73,37 +73,35 @@ class Loop extends Base {
} }
reflow() { reflow() {
return new Promise(resolve => { const { skip, repeat, greedy } = this.props;
const { skip, repeat, greedy } = this.props; const box = this.contained.getBBox();
const box = this.contained.getBBox(); const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0 };
const labelBox = this.label ? this.label.getBBox() : { width: 0, height: 0 };
let height = box.height + labelBox.height; let height = box.height + labelBox.height;
if (skip) { if (skip) {
height += 10; height += 10;
} }
if (repeat) { if (repeat) {
height += 10; height += 10;
} }
this.setBBox({ this.setBBox({
width: box.width + this.contentOffset.x * 2, width: box.width + this.contentOffset.x * 2,
height, height,
axisY: box.axisY + this.contentOffset.y, axisY: box.axisY + this.contentOffset.y,
axisX1: box.axisX1 + this.contentOffset.x, axisX1: box.axisX1 + this.contentOffset.x,
axisX2: box.axisX2 + this.contentOffset.x axisX2: box.axisX2 + this.contentOffset.x
}); });
box.offsetX = this.contentOffset.x; box.offsetX = this.contentOffset.x;
box.offsetY = this.contentOffset.y; box.offsetY = this.contentOffset.y;
this.setState({ return this.setStateAsync({
labelTransform: `translate(${ this.getBBox().width - labelBox.width - 10 } ${ this.getBBox().height + 2 })`, labelTransform: `translate(${ this.getBBox().width - labelBox.width - 10 } ${ this.getBBox().height + 2 })`,
loopPaths: [ loopPaths: [
skip && skipPath(box, greedy), skip && skipPath(box, greedy),
repeat && repeatPath(box, greedy) repeat && repeatPath(box, greedy)
].filter(Boolean).join('') ].filter(Boolean).join('')
}, resolve);
}); });
} }

View File

@ -11,28 +11,21 @@ class Pin extends Base {
} }
reflow() { reflow() {
return new Promise(resolve => { const { radius } = this.props;
const { radius } = this.props;
this.setBBox({ return this.setBBox({
width: radius * 2, width: radius * 2,
height: radius * 2 height: radius * 2
});
this.setState({
transform: `translate(${ radius } ${ radius })`
}, resolve);
}); });
} }
render() { render() {
const { radius } = this.props; const { radius } = this.props;
const { transform } = this.state || {};
const circleProps = { const circleProps = {
r: radius, r: radius,
style: style.pin, style: style.pin,
transform transform: `translate(${ radius } ${ radius })`
}; };
return <circle { ...circleProps }></circle>; return <circle { ...circleProps }></circle>;

View File

@ -7,17 +7,15 @@ import style from './style';
/** @extends React.PureComponent */ /** @extends React.PureComponent */
class Text extends Base { class Text extends Base {
reflow() { reflow() {
return new Promise(resolve => { const box = this.text.getBBox();
const box = this.text.getBBox();
this.setBBox({ this.setBBox({
width: box.width, width: box.width,
height: box.height height: box.height
}); });
this.setState({ return this.setStateAsync({
transform: `translate(${-box.x} ${-box.y})` transform: `translate(${-box.x} ${-box.y})`
}, resolve);
}); });
} }

View File

@ -88,31 +88,29 @@ class VerticalLayout extends Base {
return Promise.resolve(); return Promise.resolve();
} }
return new Promise(resolve => { const { spacing, withConnectors } = this.props;
const { spacing, withConnectors } = this.props;
const childBoxes = this.children.map(child => child.getBBox()); const childBoxes = this.children.map(child => child.getBBox());
const horizontalCenter = childBoxes.reduce((center, box) => Math.max(center, box.width / 2), 0); const horizontalCenter = childBoxes.reduce((center, box) => Math.max(center, box.width / 2), 0);
const margin = withConnectors ? connectorMargin : 0; const margin = withConnectors ? connectorMargin : 0;
const width = childBoxes.reduce((width, box) => Math.max(width, box.width), 0) + 2 * margin; const width = childBoxes.reduce((width, box) => Math.max(width, box.width), 0) + 2 * margin;
const height = childBoxes.reduce((height, box) => height + box.height, 0) + (childBoxes.length - 1) * spacing; const height = childBoxes.reduce((height, box) => height + box.height, 0) + (childBoxes.length - 1) * spacing;
this.setBBox({ width, height }, { axisY: true, axisX1: true, axisX2: true }); this.setBBox({ width, height }, { axisY: true, axisX1: true, axisX2: true });
let offset = 0; let offset = 0;
childBoxes.forEach(box => { childBoxes.forEach(box => {
box.offsetX = horizontalCenter - box.width / 2 + margin; box.offsetX = horizontalCenter - box.width / 2 + margin;
box.offsetY = offset; box.offsetY = offset;
offset += spacing + box.height; offset += spacing + box.height;
}); });
this.setState({ return this.setStateAsync({
childTransforms: this.updateChildTransforms(childBoxes), childTransforms: this.updateChildTransforms(childBoxes),
connectorPaths: withConnectors ? [ connectorPaths: withConnectors ? [
...childBoxes.map(box => this.makeCurve(box)), ...childBoxes.map(box => this.makeCurve(box)),
this.makeSide(childBoxes[0]), this.makeSide(childBoxes[0]),
this.makeSide(childBoxes[childBoxes.length - 1]) this.makeSide(childBoxes[childBoxes.length - 1])
].join('') : '' ].join('') : ''
}, resolve);
}); });
} }