StructV2/demo/Layouter/PCTree.js

251 lines
7.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

SV.registerLayout('PCTree', {
sourcesPreprocess(sources) {
let headNodes = sources.filter(item => item.type === 'PCTreeHead');
for(let i = 0; i < headNodes.length; i++){
let dataNode = {
type: 'PCTreePreHead',
id: headNodes[i].id + '_0',
data: headNodes[i].preData,
indexLeft: headNodes[i].index,
root: headNodes[i].root
};
let externalNode = {
type: 'structureExteral',
id: headNodes[0].id + '_1',
};
if(dataNode.root){
dataNode.indexTop = 'data';
headNodes[i].indexTop = ' parent firstChild';
if(headNodes[i].cursor){
externalNode.cursor = headNodes[i].cursor;
delete headNodes[i].cursor;
}else{
externalNode.external = headNodes[i].external;
delete headNodes[i].external;
}
sources.push(externalNode)
}
sources.push(dataNode)
}
return sources;
},
defineOptions() {
return {
node: {
PCTreePreHead: {
type: 'rect',
label: '[data]',
size: [60, 34],
labelOptions: {
style: { fontSize: 16 }
},
style: {
stroke: '#333',
fill: '#95e1d3',
offset: 25
}
},
PCTreeHead: {
type: 'two-cell-node',
label: '[data]',
size: [120, 34],
style: {
stroke: '#333',
fill: '#95e1d3'
}
},
PCTreeNode: {
type: 'link-list-node',
label: '[data]',
size: [60, 27],
style: {
stroke: '#333',
fill: '#00AF92'
}
},
structureExteral: {
type: 'rect',
size: [0, 0]
}
},
indexLabel: {
indexTop: { position: 'top' },
indexLeft: { position: 'left' }
},
link: {
headNext: {
sourceAnchor: 1,
targetAnchor: 6,
style: {
stroke: '#333',
endArrow: {
path: G6.Arrow.triangle(8, 6, 0),
fill: '#333'
},
startArrow: {
path: G6.Arrow.circle(2, -1),
fill: '#333'
}
}
},
next: {
sourceAnchor: 2,
targetAnchor: 6,
style: {
stroke: '#333',
endArrow: {
path: G6.Arrow.triangle(8, 6, 0),
fill: '#333'
},
startArrow: {
path: G6.Arrow.circle(2, -1),
fill: '#333'
}
}
},
loopNext: {
type: 'quadratic',
curveOffset: -100,
sourceAnchor: 2,
targetAnchor: 7,
style: {
stroke: '#333',
endArrow: 'default',
startArrow: {
path: G6.Arrow.circle(2, -1),
fill: '#333'
}
}
}
},
marker: {
external: {
type: 'pointer',
anchor: 0,
offset: 8,
style: {
fill: '#f08a5d'
}
},
cursor: {
type: 'cursor',
anchor: 0,
style: {
fill: '#f08a5d'
}
}
},
layout: {
xInterval: 50,
yInterval: 86
},
behavior: {
dragNode: ['PCTreeNode']
}
};
},
//判断node节点是否之前布局过
isUnique(value, allNodeIdValue){
let re = new RegExp("" + value);
return !re.test(allNodeIdValue);
},
/**
* 对子树进行递归布局
* @param node
* @param parent
*/
layoutItem(node, prev, layoutOptions, allNodeId, isRootNode) {
if(!node) {
return null;
}
let width = node.get('size')[0],
idValue = node.id.split('(')[1].slice(0, -1);
//有y型链表的情况不用再布局
if(this.isUnique(idValue, allNodeId.value)){
if(prev) {
node.set('y', prev.get('y'));
node.set('x', prev.get('x') + layoutOptions.xInterval + width);
}
//如果是有root标识的和其后续节点则不用记录id
//方便重更新布局
if(!isRootNode){
allNodeId.value += idValue;
}
if(node.next) {
this.layoutItem(node.next, node, layoutOptions, allNodeId, isRootNode);
}
}
},
layout(elements, layoutOptions) {
let headNode = elements.filter(item => item.type === 'PCTreeHead'),
preHeadNode = elements.filter(item => item.type === 'PCTreePreHead'),
externalNode = elements.filter(item => item.type === 'structureExteral'),
roots = elements.filter(item => item.type === 'PCTreeNode' && item.root),
height = headNode[0].get('size')[1],
width = headNode[0].get('size')[0],
i,
allNodeId = { value: ''}; //引用类型用于传参
for(i = 0; i < headNode.length; i++) {
let node = headNode[i],
preNode = preHeadNode[i];
node.set({
x: 0,
y: i * height
});
preNode.set({
x: width / 4,
y: (i + 1) * height
})
if(node.headNext) {
let y = node.get('y') + height - node.headNext.get('size')[1],
x = width + layoutOptions.xInterval * 2;
node.headNext.set({ x, y });
this.layoutItem(node.headNext, null, layoutOptions, allNodeId, false);
}
}
if(externalNode.length > 0){
externalNode[0].set({
x: -25,
y: i / 2 * height
});
}
for(i = 0; i < roots.length; i++) {
let nodeWidth = roots[0].get('size')[0],
nodeInternalSum = i * (nodeWidth + layoutOptions.xInterval);
roots[i].set({
x: headNode[0].get('x') + width + layoutOptions.xInterval * 2 + nodeInternalSum,
y: headNode[0].get('y') - layoutOptions.yInterval
})
this.layoutItem(roots[i], null, layoutOptions, allNodeId, true);
}
}
});