1
0
mirror of https://github.com/ellmau/adf-obdd.git synced 2025-12-20 09:39:38 +01:00

Introduce custom node type for nicer layout

This commit is contained in:
monsterkrampe 2022-09-02 11:46:15 +02:00
parent 9ab4ff3de4
commit b8038dccfa
No known key found for this signature in database
GPG Key ID: B8ADC1F5A5CE5057

View File

@ -2,6 +2,129 @@ import React, { useEffect, useRef } from 'react';
import G6 from '@antv/g6'; import G6 from '@antv/g6';
G6.registerNode('nodeWithFlag', {
draw(cfg, group) {
console.log('cfg', cfg);
const mainWidth = Math.max(30, 5 * cfg.mainLabel.length + 10);
const mainHeight = 30;
const keyShape = group.addShape('rect', {
attrs: {
width: mainWidth,
height: mainHeight,
radius: 2,
fill: cfg.fill || 'white',
stroke: 'black',
lineWidth: cfg.lineWidth,
opacity: cfg.opacity,
},
name: 'rectMainLabel',
draggable: true
});
group.addShape('text', {
attrs: {
x: mainWidth / 2,
y: mainHeight / 2,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.mainLabel,
fill: '#212121',
fontFamily: 'Roboto',
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'textMailLabel',
// allow the shape to response the drag events
draggable: true
});
if (cfg.subLabel) {
const subWidth = 5 * cfg.subLabel.length + 4;
const subHeight = 20;
const subRectX = mainWidth - 4;
const subRectY = -subHeight + 4;
group.addShape('rect', {
attrs: {
x: subRectX,
y: subRectY,
width: subWidth,
height: subHeight,
radius: 1,
fill: '#4caf50',
stroke: '#1b5e20',
opacity: cfg.opacity,
},
name: 'rectMainLabel',
draggable: true
});
group.addShape('text', {
attrs: {
x: subRectX + subWidth / 2,
y: subRectY + subHeight / 2,
textAlign: 'center',
textBaseline: 'middle',
text: cfg.subLabel,
fill: '#212121',
fontFamily: 'Roboto',
fontSize: 10,
},
// must be assigned in G6 3.3 and later versions. it can be any value you want
name: 'textMailLabel',
// allow the shape to response the drag events
draggable: true
});
}
return keyShape;
},
getAnchorPoints() {
return [[0.5, 0], [0, 0.5], [1, 0.5], [0.5, 1]];
},
//nodeStateStyles: {
//hover: {
//fill: 'lightsteelblue',
//},
//highlight: {
//lineWidth: 3,
//},
//lowlight: {
//opacity: 0.3,
//},
//},
setState(name, value, item) {
const group = item.getContainer();
const shape = group.get('children')[0]; // Find the first graphics shape of the node. It is determined by the order of being added
if (name === 'hover') {
if (value) {
shape.attr('fill', 'lightsteelblue');
} else {
shape.attr('fill', 'white');
}
}
if (name === 'highlight') {
if (value) {
shape.attr('lineWidth', 3);
} else {
shape.attr('lineWidth', 1);
}
}
if (name === 'lowlight') {
if (value) {
shape.attr('opacity', 0.3);
} else {
shape.attr('opacity', 1);
}
}
},
});
interface Props { interface Props {
graph: { graph: {
lo_edges: [number, number][], lo_edges: [number, number][],
@ -34,36 +157,36 @@ function Graph(props: Props) {
default: ['drag-canvas', 'zoom-canvas', 'drag-node'], default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
}, },
layout: { type: 'dagre' }, layout: { type: 'dagre' },
defaultNode: { //defaultNode: {
anchorPoints: [[0.5, 0], [0, 0.5], [1, 0.5], [0.5, 1]], //anchorPoints: [[0.5, 0], [0, 0.5], [1, 0.5], [0.5, 1]],
type: 'rect', //type: 'rect',
style: { //style: {
radius: 2, //radius: 2,
}, //},
labelCfg: { //labelCfg: {
style: { //style: {
// fontWeight: 700, //// fontWeight: 700,
fontFamily: 'Roboto', //fontFamily: 'Roboto',
}, //},
}, //},
}, //},
defaultNode: { type: 'nodeWithFlag' },
defaultEdge: { defaultEdge: {
style: { style: {
endArrow: true, endArrow: true,
}, },
}, },
nodeStateStyles: { //nodeStateStyles: {
hover: { //hover: {
fill: 'lightsteelblue', //fill: 'lightsteelblue',
}, //},
highlight: { //highlight: {
stroke: '#000', //lineWidth: 3,
lineWidth: 3, //},
}, //lowlight: {
lowlight: { //opacity: 0.3,
opacity: 0.3, //},
}, //},
},
edgeStateStyles: { edgeStateStyles: {
lowlight: { lowlight: {
opacity: 0.3, opacity: 0.3,
@ -85,6 +208,13 @@ function Graph(props: Props) {
const nodeItem = e.item; // Get the target item const nodeItem = e.item; // Get the target item
graph.setItemState(nodeItem, 'hover', false); // Set the state 'hover' of the item to be false graph.setItemState(nodeItem, 'hover', false); // Set the state 'hover' of the item to be false
}); });
},
[],
);
useEffect(
() => {
const graph = graphRef.current;
// Click a node // Click a node
graph.on('node:click', (e) => { graph.on('node:click', (e) => {
@ -172,9 +302,11 @@ function Graph(props: Props) {
// graph.setItemState(edge, 'lowlight', false); // graph.setItemState(edge, 'lowlight', false);
// }); // });
}); });
return () => { graph.off('node:click') };
}, },
[], [graphProps],
); )
useEffect( useEffect(
() => { () => {
@ -182,24 +314,25 @@ function Graph(props: Props) {
const nodes = Object.keys(graphProps.node_labels).map((id) => { const nodes = Object.keys(graphProps.node_labels).map((id) => {
const mainLabel = graphProps.node_labels[id]; const mainLabel = graphProps.node_labels[id];
const subLabel = graphProps.tree_root_labels[id].length > 0 ? `Root for: ${graphProps.tree_root_labels[id].join(' ; ')}` : ''; const subLabel = graphProps.tree_root_labels[id].length > 0 ? `Root for: ${graphProps.tree_root_labels[id].join(' ; ')}` : undefined;
const label = subLabel.length > 0 ? `${mainLabel}\n${subLabel}` : mainLabel; //const label = subLabel.length > 0 ? `${mainLabel}\n${subLabel}` : mainLabel;
return { return {
id: id.toString(), id: id.toString(),
label, mainLabel,
style: { subLabel,
height: subLabel.length > 0 ? 60 : 30, //style: {
width: Math.max(30, 5 * mainLabel.length + 10, 5 * subLabel.length + 10), //height: subLabel.length > 0 ? 60 : 30,
}, //width: Math.max(30, 5 * mainLabel.length + 10, 5 * subLabel.length + 10),
//},
}; };
}); });
const edges = graphProps.lo_edges.map(([source, target]) => ({ const edges = graphProps.lo_edges.map(([source, target]) => ({
id: `LO_${source}_${target}`, source: source.toString(), target: target.toString(), style: { stroke: 'red', lineWidth: 2 }, id: `LO_${source}_${target}`, source: source.toString(), target: target.toString(), style: { stroke: '#ed6c02', lineWidth: 2 },
})) }))
.concat(graphProps.hi_edges.map(([source, target]) => ({ .concat(graphProps.hi_edges.map(([source, target]) => ({
id: `HI_${source}_${target}`, source: source.toString(), target: target.toString(), style: { stroke: 'green', lineWidth: 2 }, id: `HI_${source}_${target}`, source: source.toString(), target: target.toString(), style: { stroke: '#1976d2', lineWidth: 2 },
}))); })));
graph.data({ graph.data({
@ -211,7 +344,13 @@ function Graph(props: Props) {
[graphProps], [graphProps],
); );
return <div ref={ref} style={{ overflow: 'hidden' }} />; return <>
<div ref={ref} style={{ overflow: 'hidden' }} />
<div>
<span style={{ color: '#ed6c02' }}>lo edge (condition is false)</span>
{' '}
<span style={{ color: '#1976d2' }}>hi edge (condition is true)</span>
</div></>;
} }
export default Graph; export default Graph;