Reorder top-level location boxes after ELK layout

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ian Gulliver
2026-01-24 16:33:56 -08:00
parent a6ce2e4696
commit 01f14cc3f7

View File

@@ -104,10 +104,12 @@
return chain;
}
let topLevelOrder = [];
function doLayout() {
cy.layout({
const layout = cy.layout({
name: 'elk',
fit: true,
fit: false,
padding: 50,
nodeDimensionsIncludeLabels: true,
elk: {
@@ -119,8 +121,44 @@
'elk.layered.spacing.nodeNodeBetweenLayers': 100,
'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',
'elk.hierarchyHandling': 'INCLUDE_CHILDREN'
},
stop: function() {
reorderTopLevel();
cy.fit(50);
}
}).run();
});
layout.run();
}
function reorderTopLevel() {
if (topLevelOrder.length < 2) return;
const boxes = topLevelOrder.map(locId => {
const node = cy.getElementById(locId);
if (node.empty()) return null;
const bb = node.boundingBox();
return { id: locId, bb: bb, height: bb.y2 - bb.y1 };
}).filter(b => b !== null);
if (boxes.length < 2) return;
const minY = Math.min(...boxes.map(b => b.bb.y1));
const gap = 50;
let targetY = minY;
const targets = boxes.map(box => {
const result = { id: box.id, deltaY: targetY - box.bb.y1 };
targetY += box.height + gap;
return result;
});
targets.forEach(target => {
const node = cy.getElementById(target.id);
node.descendants().filter(n => !n.isParent()).forEach(n => {
const pos = n.position();
n.position({ x: pos.x, y: pos.y + target.deltaY });
});
});
}
async function init() {
@@ -216,6 +254,18 @@
});
});
// Find top-level locations and sort by config order
topLevelOrder = sortedLocations
.filter(locId => {
const meta = locationMeta.get(locId);
return !meta.parentId;
})
.sort((a, b) => {
const metaA = locationMeta.get(a);
const metaB = locationMeta.get(b);
return metaA.order - metaB.order;
});
cy = cytoscape({
container: document.getElementById('cy'),
elements: elements,