diff --git a/components/graph/base.js b/components/graph/base.js index 7f33588..9555246 100644 --- a/components/graph/base.js +++ b/components/graph/base.js @@ -1,5 +1,9 @@ /* global document */ +const { + merge, +} = require('ramda'); + const r = require('r-dom'); const { @@ -13,8 +17,18 @@ const math = require('mathjs'); class GraphView extends GraphViewBase { constructor(props) { + if (!props.layoutEngine) { + props = merge(props, { + layoutEngineType: 'None', + }); + } + super(props); + if (props.layoutEngine) { + this.layoutEngine = props.layoutEngine; + } + Object.assign(this, { _super_handleNodeMove: this.handleNodeMove, handleNodeMove: this.constructor.prototype.handleNodeMove.bind(this), @@ -27,6 +41,16 @@ class GraphView extends GraphViewBase { }); } + static getDerivedStateFromProps(props, state) { + const derivedState = super.getDerivedStateFromProps(props, state); + + if (props.layoutEngine) { + derivedState.nodes = props.layoutEngine.adjustNodes(derivedState.nodes, derivedState.nodesMap); + } + + return derivedState; + } + shouldComponentUpdate(nextProps, nextState) { return super.shouldComponentUpdate(nextProps, nextState) || this.state.edgeEndNode !== nextState.edgeEndNode; @@ -123,6 +147,10 @@ class GraphView extends GraphViewBase { } } +GraphView.defaultProps = merge(GraphViewBase.defaultProps, { + layoutEngineType: null, +}); + const size = 120; class Node extends NodeBase { diff --git a/components/graph/index.js b/components/graph/index.js index 405c878..2c58ab0 100644 --- a/components/graph/index.js +++ b/components/graph/index.js @@ -41,6 +41,8 @@ const { Edge, } = require('./base'); +const LayoutEngine = require('./layout-engine'); + const dgoToPai = new WeakMap(); const key = pao => `${pao.type}-${pao.index}`; @@ -422,6 +424,8 @@ const renderEdgeText = state => ({ data: dgo, transform, selected }) => { ])); }; +const layoutEngine = new LayoutEngine(); + class Graph extends React.Component { constructor(props) { super(props); @@ -579,22 +583,6 @@ class Graph extends React.Component { return filteredNodeKeys.has(edge.source) && filteredNodeKeys.has(edge.target); }, edges); - nodes.forEach(node => { - if (node.x !== undefined) { - return; - } - - if (node.type === 'source') { - node.x = 0 * size; - } else if (node.type === 'sink') { - node.x = 10 * size; - } else { - node.x = (2 * size) + (Math.round(6 * Math.random()) * size); - } - - node.y = Math.random() * 1200; - }); - nodes.forEach(node => { const pai = getPaiByTypeAndIndex(node.type, node.index)({ pulse: this.props }); dgoToPai.set(node, pai); @@ -632,6 +620,8 @@ class Graph extends React.Component { edgeArrowSize: 64, + layoutEngine, + backgroundFillId: '#background-pattern', renderDefs, diff --git a/components/graph/layout-engine.js b/components/graph/layout-engine.js new file mode 100644 index 0000000..0df197b --- /dev/null +++ b/components/graph/layout-engine.js @@ -0,0 +1,36 @@ + +const size = 200; + +module.exports = class LayoutEngine { + constructor(graphViewProps) { + this.graphViewProps = graphViewProps; + } + + calculatePosition(node) { + return node; + } + + adjustNodes(nodes, nodesMap) { + nodes.forEach(node => { + if (node.x !== undefined) { + return; + } + + if (node.type === 'source') { + node.x = 0 * size; + } else if (node.type === 'sink') { + node.x = 10 * size; + } else { + node.x = (2 * size) + (Math.round(6 * Math.random()) * size); + } + + node.y = Math.random() * 1200; + }); + + return nodes; + } + + getPositionForNode(node) { + return this.calculatePosition(node); + } +};