Shift+A wraps selected nodes in auto-layout frame
Single frame selected: toggles auto-layout on/off. Any other selection: creates a new frame around the selected nodes, reparents them into it, and enables vertical auto-layout with HUG sizing.
This commit is contained in:
parent
10c0a39ebe
commit
ecfc6dd0c2
|
|
@ -74,8 +74,10 @@ export function useKeyboard(store: EditorStore) {
|
|||
if (e.shiftKey && e.key === 'A') {
|
||||
e.preventDefault()
|
||||
const node = store.selectedNode.value
|
||||
if (node && node.type === 'FRAME') {
|
||||
if (node && node.type === 'FRAME' && store.selectedNodes.value.length === 1) {
|
||||
store.setLayoutMode(node.id, node.layoutMode === 'NONE' ? 'VERTICAL' : 'NONE')
|
||||
} else if (store.selectedNodes.value.length > 0) {
|
||||
store.wrapInAutoLayout()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,6 +232,57 @@ export function createEditorStore() {
|
|||
requestRender()
|
||||
}
|
||||
|
||||
function wrapInAutoLayout() {
|
||||
const nodes = selectedNodes.value
|
||||
if (nodes.length === 0) return
|
||||
|
||||
// Find common parent
|
||||
const parentId = nodes[0].parentId ?? graph.rootId
|
||||
const sameParent = nodes.every((n) => (n.parentId ?? graph.rootId) === parentId)
|
||||
if (!sameParent) return
|
||||
|
||||
// Compute bounding box in absolute coords
|
||||
let minX = Infinity
|
||||
let minY = Infinity
|
||||
let maxX = -Infinity
|
||||
let maxY = -Infinity
|
||||
for (const n of nodes) {
|
||||
const abs = graph.getAbsolutePosition(n.id)
|
||||
minX = Math.min(minX, abs.x)
|
||||
minY = Math.min(minY, abs.y)
|
||||
maxX = Math.max(maxX, abs.x + n.width)
|
||||
maxY = Math.max(maxY, abs.y + n.height)
|
||||
}
|
||||
|
||||
// Position relative to parent
|
||||
const parentAbs =
|
||||
parentId === graph.rootId ? { x: 0, y: 0 } : graph.getAbsolutePosition(parentId)
|
||||
|
||||
const frame = graph.createNode('FRAME', parentId, {
|
||||
name: 'Frame',
|
||||
x: minX - parentAbs.x,
|
||||
y: minY - parentAbs.y,
|
||||
width: maxX - minX,
|
||||
height: maxY - minY,
|
||||
layoutMode: 'VERTICAL',
|
||||
primaryAxisSizing: 'HUG',
|
||||
counterAxisSizing: 'HUG',
|
||||
primaryAxisAlign: 'MIN',
|
||||
counterAxisAlign: 'MIN',
|
||||
fills: [{ type: 'SOLID', color: { r: 1, g: 1, b: 1, a: 1 }, opacity: 1, visible: true }]
|
||||
})
|
||||
|
||||
// Reparent nodes into the new frame
|
||||
for (const n of nodes) {
|
||||
graph.reparentNode(n.id, frame.id)
|
||||
}
|
||||
|
||||
computeLayout(graph, frame.id)
|
||||
runLayoutForNode(frame.id)
|
||||
state.selectedIds = new Set([frame.id])
|
||||
requestRender()
|
||||
}
|
||||
|
||||
function createShape(
|
||||
type: NodeType,
|
||||
x: number,
|
||||
|
|
@ -460,6 +511,7 @@ export function createEditorStore() {
|
|||
openFigFile,
|
||||
updateNode,
|
||||
setLayoutMode,
|
||||
wrapInAutoLayout,
|
||||
createShape,
|
||||
duplicateSelected,
|
||||
writeCopyData,
|
||||
|
|
|
|||
Loading…
Reference in a new issue