Custom layout engine
This commit is contained in:
parent
c3deec41d7
commit
e2b2a4fc55
|
@ -1,5 +1,9 @@
|
||||||
/* global document */
|
/* global document */
|
||||||
|
|
||||||
|
const {
|
||||||
|
merge,
|
||||||
|
} = require('ramda');
|
||||||
|
|
||||||
const r = require('r-dom');
|
const r = require('r-dom');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -13,8 +17,18 @@ const math = require('mathjs');
|
||||||
|
|
||||||
class GraphView extends GraphViewBase {
|
class GraphView extends GraphViewBase {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
if (!props.layoutEngine) {
|
||||||
|
props = merge(props, {
|
||||||
|
layoutEngineType: 'None',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
|
if (props.layoutEngine) {
|
||||||
|
this.layoutEngine = props.layoutEngine;
|
||||||
|
}
|
||||||
|
|
||||||
Object.assign(this, {
|
Object.assign(this, {
|
||||||
_super_handleNodeMove: this.handleNodeMove,
|
_super_handleNodeMove: this.handleNodeMove,
|
||||||
handleNodeMove: this.constructor.prototype.handleNodeMove.bind(this),
|
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) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return super.shouldComponentUpdate(nextProps, nextState) ||
|
return super.shouldComponentUpdate(nextProps, nextState) ||
|
||||||
this.state.edgeEndNode !== nextState.edgeEndNode;
|
this.state.edgeEndNode !== nextState.edgeEndNode;
|
||||||
|
@ -123,6 +147,10 @@ class GraphView extends GraphViewBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GraphView.defaultProps = merge(GraphViewBase.defaultProps, {
|
||||||
|
layoutEngineType: null,
|
||||||
|
});
|
||||||
|
|
||||||
const size = 120;
|
const size = 120;
|
||||||
|
|
||||||
class Node extends NodeBase {
|
class Node extends NodeBase {
|
||||||
|
|
|
@ -41,6 +41,8 @@ const {
|
||||||
Edge,
|
Edge,
|
||||||
} = require('./base');
|
} = require('./base');
|
||||||
|
|
||||||
|
const LayoutEngine = require('./layout-engine');
|
||||||
|
|
||||||
const dgoToPai = new WeakMap();
|
const dgoToPai = new WeakMap();
|
||||||
|
|
||||||
const key = pao => `${pao.type}-${pao.index}`;
|
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 {
|
class Graph extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -579,22 +583,6 @@ class Graph extends React.Component {
|
||||||
return filteredNodeKeys.has(edge.source) && filteredNodeKeys.has(edge.target);
|
return filteredNodeKeys.has(edge.source) && filteredNodeKeys.has(edge.target);
|
||||||
}, edges);
|
}, 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 => {
|
nodes.forEach(node => {
|
||||||
const pai = getPaiByTypeAndIndex(node.type, node.index)({ pulse: this.props });
|
const pai = getPaiByTypeAndIndex(node.type, node.index)({ pulse: this.props });
|
||||||
dgoToPai.set(node, pai);
|
dgoToPai.set(node, pai);
|
||||||
|
@ -632,6 +620,8 @@ class Graph extends React.Component {
|
||||||
|
|
||||||
edgeArrowSize: 64,
|
edgeArrowSize: 64,
|
||||||
|
|
||||||
|
layoutEngine,
|
||||||
|
|
||||||
backgroundFillId: '#background-pattern',
|
backgroundFillId: '#background-pattern',
|
||||||
|
|
||||||
renderDefs,
|
renderDefs,
|
||||||
|
|
36
components/graph/layout-engine.js
Normal file
36
components/graph/layout-engine.js
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user