From fdf5a8d6c589929ea390a6c72f9bf9b2f1c4ac30 Mon Sep 17 00:00:00 2001 From: STEINNI Date: Mon, 12 Jan 2026 14:12:27 +0000 Subject: [PATCH] Better windows height & overflow + graflow autoplace at drawing --- bzGraflow.js | 59 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/bzGraflow.js b/bzGraflow.js index 3c0c4b1..b5ae82e 100644 --- a/bzGraflow.js +++ b/bzGraflow.js @@ -104,8 +104,8 @@ class BZgraflow extends Buildoz{ } if(typeof(node.data)=='object') Object.assign(this.stagedNodes[id].dataset, node.data) const portEls = this.stagedNodes[id].querySelectorAll('.port') - this.stagedNodes[id].style.left = `${node.coords.x}px` - this.stagedNodes[id].style.top = `${node.coords.y}px` + this.stagedNodes[id].style.left = (node.coords && node.coords.x) ? `${node.coords.x}px` : '10%' + this.stagedNodes[id].style.top = (node.coords && node.coords.y) ? `${node.coords.y}px` : '10%' this.stagedNodes[id].dataset.id = id this.stagedNodes[id].ports = Object.fromEntries(Array.from(portEls).map(item => ([item.dataset.id, { ...item.dataset, el:item }]))) this.nodesContainer.append(this.stagedNodes[id]) @@ -129,12 +129,21 @@ class BZgraflow extends Buildoz{ } refresh(){ + let forceAutoplace = false for(const node of this.flow.nodes){ + if((!node.coords) || (!node.coords.x) ||(!node.coords.y)) forceAutoplace=true this.addNode(node) } for(const link of this.flow.links){ this.addWire(link) - } + } + + if(forceAutoplace){ + const bb=this.getBoundingClientRect() + //TODO compute tensions from nodes + if(bb.width > bb.height) this.autoPlace('horizontal', 80, 30, 500) + else this.autoPlace('vertical', 80, 30, 200) + } } bezier(idNode1, idPort1, idNode2, idPort2, tensionMin=60) { @@ -171,7 +180,7 @@ class BZgraflow extends Buildoz{ return `M ${x1} ${y1} C ${c1x} ${c1y}, ${c2x} ${c2y}, ${x2} ${y2}` } - autoPlace(orientation = 'horizontal', gapx = 80, gapy = 30){ + autoPlace(orientation = 'horizontal', gapx = 80, gapy = 30, tween=1000){ if(this.hasAnyLoop(this.flow.nodes, this.flow.links)){ console.warn('Loop(s) detected... Cannot auto-place !') return @@ -219,7 +228,7 @@ class BZgraflow extends Buildoz{ for(const nid of layer){ const bb = this.stagedNodes[nid].getBoundingClientRect() wMax = (bb.width > wMax) ? bb.width : wMax - this.moveNode(nid, x, y, 1000) + this.moveNode(nid, x, y, tween) y += gapy + bb.height } x += wMax + gapx @@ -232,7 +241,7 @@ class BZgraflow extends Buildoz{ for(const nid of layer){ const bb = this.stagedNodes[nid].getBoundingClientRect() hMax = (bb.height > hMax) ? bb.width : hMax - this.moveNode(nid, x, y, 1000) + this.moveNode(nid, x, y, tween) x += gapx + bb.width } y += hMax + gapy @@ -271,13 +280,11 @@ class BZgraflow extends Buildoz{ const parentbb = this.stagedNodes[nid].parentElement.getBoundingClientRect() const x0=bb.x - parentbb.x const y0 = bb.y - parentbb.y - console.log('y0:', y0, bb) function frame(t) { const p = Math.min((t - t0) / duration, 1) const k = p * p * (3 - 2 * p) // smoothstep const x = x0 + (destx - x0) * k - const y = y0 + (desty - y0) * k - + const y = y0 + (desty - y0) * k this.stagedNodes[nid].style.left = `${x}px` this.stagedNodes[nid].style.top = `${y}px` this.updateWires(nid) @@ -353,7 +360,41 @@ class BZgraflow extends Buildoz{ } return(this.flow.nodes.map(n => n.id).some(dfs)) } + + getLoopingLinks(nodes, links) { + const linkIndexes = [] + const adj = {}; + this.flow.nodes.forEach(node => adj[node.id] = []) + for(let [idx, link] of this.flow.links.entries()){ + if(link.from[0] == link.to[0]) linkIndexes.push(idx) //self loops + adj[link.from[0]].push([link.to[0], idx]) + } + + const visiting = new Set() + const visited = new Set() + const loops = new Set() + const dfs = (nid) => { + if(visiting.has(nid)) { + loops.push() + return(true) + } + + if(visited.has(nid)) return(false) + visiting.add(nid) + for(const m of adj[nid]) { + if(dfs(m)) { + return(true) + } + } + visiting.delete(nid) + visited.add(nid) + return(false) + } + return(this.flow.nodes.map(n => n.id).some(dfs)) + } + + } Buildoz.define('graflow', BZgraflow)