fix: editor layout and SceneGraph refinements
This commit is contained in:
@@ -7,7 +7,7 @@ import '@vue-flow/core/dist/style.css'
|
||||
import '@vue-flow/controls/dist/style.css'
|
||||
import '@vue-flow/core/dist/theme-default.css'
|
||||
import type { Connection } from '@vue-flow/core'
|
||||
import { computePositions } from '../composables/useLayout'
|
||||
import { computePositions, savePosition } from '../composables/useLayout'
|
||||
|
||||
const props = defineProps<{
|
||||
sceneNodes: { id: string; label: string }[]
|
||||
@@ -24,7 +24,7 @@ const emit = defineEmits<{
|
||||
|
||||
const nodes = ref<any[]>([])
|
||||
const edges = ref<any[]>([])
|
||||
const { onNodeClick, onConnect, onNodeContextMenu, fitView } = useVueFlow()
|
||||
const { onNodeClick, onConnect, onNodeContextMenu, onNodeDragStop, fitView } = useVueFlow()
|
||||
const ctxMenuVisible = ref(false)
|
||||
const ctxMenuX = ref(0)
|
||||
const ctxMenuY = ref(0)
|
||||
@@ -130,6 +130,11 @@ function closeMenu() {
|
||||
ctxMenuVisible.value = false
|
||||
}
|
||||
|
||||
onNodeDragStop((ev) => {
|
||||
const pos = ev.node.position
|
||||
savePosition(ev.node.id, Math.round(pos.x), Math.round(pos.y))
|
||||
})
|
||||
|
||||
onConnect((conn: Connection) => {
|
||||
if (conn.source && conn.target) emit('addEdge', conn.source, conn.target)
|
||||
})
|
||||
|
||||
@@ -12,12 +12,39 @@ interface EdgeInfo {
|
||||
|
||||
const NODE_W = 180
|
||||
const NODE_H = 60
|
||||
const POSITIONS_KEY = 'editor_positions'
|
||||
|
||||
export function loadSavedPositions(): Record<string, { x: number; y: number }> {
|
||||
try {
|
||||
return JSON.parse(localStorage.getItem(POSITIONS_KEY) || '{}')
|
||||
} catch { return {} }
|
||||
}
|
||||
|
||||
export function savePosition(nodeId: string, x: number, y: number) {
|
||||
const saved = loadSavedPositions()
|
||||
saved[nodeId] = { x, y }
|
||||
localStorage.setItem(POSITIONS_KEY, JSON.stringify(saved))
|
||||
}
|
||||
|
||||
export function computePositions(
|
||||
nodes: NodeInfo[],
|
||||
edges: EdgeInfo[],
|
||||
_startScene: string,
|
||||
): Map<string, { x: number; y: number }> {
|
||||
const saved = loadSavedPositions()
|
||||
const result = new Map<string, { x: number; y: number }>()
|
||||
|
||||
const unsaved: NodeInfo[] = []
|
||||
for (const n of nodes) {
|
||||
if (saved[n.id]) {
|
||||
result.set(n.id, saved[n.id])
|
||||
} else {
|
||||
unsaved.push(n)
|
||||
}
|
||||
}
|
||||
|
||||
if (unsaved.length === 0) return result
|
||||
|
||||
const g = new dagre.graphlib.Graph()
|
||||
g.setGraph({
|
||||
rankdir: 'LR',
|
||||
@@ -28,11 +55,11 @@ export function computePositions(
|
||||
})
|
||||
g.setDefaultEdgeLabel(() => ({}))
|
||||
|
||||
for (const n of nodes) {
|
||||
for (const n of unsaved) {
|
||||
g.setNode(n.id, { width: NODE_W, height: NODE_H })
|
||||
}
|
||||
|
||||
const nodeIds = new Set(nodes.map((n) => n.id))
|
||||
const nodeIds = new Set(unsaved.map((n) => n.id))
|
||||
for (const e of edges) {
|
||||
if (nodeIds.has(e.source) && nodeIds.has(e.target)) {
|
||||
g.setEdge(e.source, e.target)
|
||||
@@ -41,13 +68,12 @@ export function computePositions(
|
||||
|
||||
dagre.layout(g)
|
||||
|
||||
const positions = new Map<string, { x: number; y: number }>()
|
||||
for (const n of nodes) {
|
||||
for (const n of unsaved) {
|
||||
const node = g.node(n.id)
|
||||
if (node) {
|
||||
positions.set(n.id, { x: node.x - NODE_W / 2, y: node.y - NODE_H / 2 })
|
||||
result.set(n.id, { x: node.x - NODE_W / 2, y: node.y - NODE_H / 2 })
|
||||
}
|
||||
}
|
||||
|
||||
return positions
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user