#3358 Recursive positioning

This commit is contained in:
Knut Sveidqvist
2023-10-03 20:12:33 +02:00
parent f00871a6b4
commit c8d155c455
2 changed files with 118 additions and 25 deletions

View File

@@ -65,8 +65,8 @@
<body>
<pre id="diagram" class="mermaid">
block-beta
%% id1("Wide 1")
id2("2")
id1("Wide 1")
%%id2("2")
block
id3["I am a wide one"]
block
@@ -79,9 +79,26 @@ block-beta
</pre>
<pre id="diagram" class="mermaid">
block-beta
id3["I am a wide one"]
id4
id1
block
id2
end
</pre>
<pre id="diagram" class="mermaid">
block-beta
id1["Hello"]
block
id2["to"]
id3["the"]
id4["World"]
end
</pre>
<pre id="diagram" class="mermaid2">
block-beta
block
id2["I am a wide one"]
id1
end
</pre>

View File

@@ -1,12 +1,14 @@
import { BlockDB } from './blockDB.js';
import type { Block } from './blockTypes.js';
const padding = 10;
function calcBlockSizes(block: Block, db: BlockDB) {
console.log('calculateSize (start)', block.id, block?.size?.x, block?.size?.width);
const totalWidth = 0;
const totalHeight = 0;
let maxWidth = 0;
let maxHeight = 0;
const padding = 20;
if (block.children) {
for (const child of block.children) {
@@ -15,6 +17,7 @@ function calcBlockSizes(block: Block, db: BlockDB) {
// find max width of children
for (const child of block.children) {
const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
// console.log('APA', child.id, width, height, x, y);
if (width > maxWidth) {
maxWidth = width;
}
@@ -28,22 +31,24 @@ function calcBlockSizes(block: Block, db: BlockDB) {
if (child.size) {
child.size.width = maxWidth;
child.size.height = maxHeight;
child.size.x = 0;
child.size.y = 0;
}
}
// Position items relative to self
let x = -padding / 2;
const y = 0;
// // Position items relative to self
// let x = -padding / 2;
// const y = 0;
let accumulatedPaddingX = 0;
for (const child of block.children) {
if (child.size) {
child.size.x = x;
child.size.y = y;
x += maxWidth + padding;
}
accumulatedPaddingX += padding;
}
// let accumulatedPaddingX = 0;
// for (const child of block.children) {
// if (child.size) {
// child.size.x = x;
// child.size.y = y;
// x += maxWidth + padding;
// }
// accumulatedPaddingX += padding;
// }
}
if (block.children?.length > 0) {
const numChildren = block.children.length;
@@ -54,19 +59,88 @@ function calcBlockSizes(block: Block, db: BlockDB) {
y: 0,
};
}
console.log('layoutBlock (done)', block);
console.log('calculateSize APA (done)', block.id, block.size.x, block.size.width);
}
function layoutBlocks(block: Block, db: BlockDB) {
console.log('layout blocks (block)', block.id, 'x:', block.size.x, 'width:', block.size.width);
if (
block.children && // find max width of children
block.children.length > 0
) {
const width = block?.children[0]?.size?.width || 0;
const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding;
let posX = (block?.size?.x || 0) - widthOfChildren / 2;
const posY = 0;
const parentX = block?.size?.x || 0 - block.children.length;
const parentWidth = block?.size?.width || 0;
console.log('widthOfChildren', widthOfChildren, 'posX', posX, 'parentX', parentX);
// let first = true;
for (const child of block.children) {
console.log(
'layout blocks (child)',
child.id,
'x:',
child?.size?.x,
'width:',
child?.size?.width,
'posX:',
posX,
block?.size?.x,
widthOfChildren / 2,
widthOfChildren / 2
);
if (!child.size) {
continue;
}
const { width, height } = child.size;
child.size.x = posX + width / 2;
posX += width + padding;
child.size.y = posY;
// posY += height + padding;
if (child.children) {
layoutBlocks(child, db);
}
}
}
}
function positionBlock(parent: Block, block: Block, db: BlockDB) {
console.log('layout position block', parent.id, parent?.size?.x, block.id, block?.size?.x);
console.log(
'layout position block',
parent.id,
parent?.size?.x,
block.id,
block?.size?.x,
'width:',
block?.size?.width
);
let parentX = 0;
let parentWidth = 0;
let y = 0;
if (parent) {
if (parent.id !== 'root') {
parentX = parent?.size?.x || 0;
parentWidth = parent?.size?.width || 0;
y = parent?.size?.y || 0;
}
if (block.size && block.id !== 'root') {
block.size.x = parentX + block.size.x + -block.size.width / 2;
console.log(
'layout position block (calc)',
'x:',
parentX,
parentWidth / 2,
block.id,
'x:',
block.size.x,
block.size.width
);
// block.size.x = parentX + block.size.x + -block.size.width / 2;
block.size.x =
parentX < 0 ? parentX + block.size.x : parentX + block.size.x + -block.size.width / 2;
// block.size.x = parentX - parentWidth + Math.abs(block.size.x) / 2;
block.size.y = block.size.y + y;
}
if (block.children) {
@@ -82,10 +156,11 @@ let maxX = 0;
let maxY = 0;
function findBounds(block: Block) {
if (block.size) {
if (block.size && block.id !== 'root') {
const { x, y, width, height } = block.size;
if (x - width / 2 < minX) {
minX = x - width / 2;
// console.log('Here APA minX', block.id, x, width, minX);
}
if (y - height / 2 < minY) {
minY = y - height / 2;
@@ -108,8 +183,9 @@ export function layout(db: BlockDB) {
const blocks = db.getBlocks();
const root = { id: 'root', type: 'composite', children: blocks } as Block;
calcBlockSizes(root, db);
layoutBlocks(root, db);
// Position blocks relative to parents
positionBlock(root, root, db);
// positionBlock(root, root, db);
console.log('getBlocks', JSON.stringify(db.getBlocks(), null, 2));
minX = 0;
@@ -117,7 +193,7 @@ export function layout(db: BlockDB) {
maxX = 0;
maxY = 0;
findBounds(root);
console.log('Here maxX', maxX);
// console.log('Here maxX', minX, '--', maxX);
const height = maxY - minY;
const width = maxX - minX;
return { x: minX, y: minY, width, height };