|
import { layout, Tree } from './algorithm' |
|
|
|
class BoundingBox { |
|
|
|
|
|
|
|
|
|
constructor(gap, bottomPadding) { |
|
this.gap = gap |
|
this.bottomPadding = bottomPadding |
|
} |
|
|
|
addBoundingBox(width, height) { |
|
return { width: width + this.gap, height: height + this.bottomPadding } |
|
} |
|
|
|
|
|
|
|
|
|
removeBoundingBox(x, y) { |
|
return { x: x + this.gap / 2, y } |
|
} |
|
} |
|
|
|
class Layout { |
|
constructor(boundingBox) { |
|
this.bb = boundingBox |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
layout(treeData) { |
|
const tree = this.convert(treeData) |
|
layout(tree) |
|
const { boundingBox, result } = this.assignLayout(tree, treeData) |
|
|
|
return { result, boundingBox } |
|
} |
|
|
|
|
|
|
|
|
|
convert(treeData, y = 0) { |
|
if (treeData === null) return null |
|
|
|
const { width, height } = this.bb.addBoundingBox( |
|
treeData.width, |
|
treeData.height |
|
) |
|
let children = [] |
|
if (treeData.children && treeData.children.length) { |
|
for (let i = 0; i < treeData.children.length; i++) { |
|
children[i] = this.convert(treeData.children[i], y + height) |
|
} |
|
} |
|
|
|
return new Tree(width, height, y, children) |
|
} |
|
|
|
|
|
|
|
|
|
|
|
assignCoordinates(tree, treeData) { |
|
const { x, y } = this.bb.removeBoundingBox(tree.x, tree.y) |
|
treeData.x = x |
|
treeData.y = y |
|
for (let i = 0; i < tree.c.length; i++) { |
|
this.assignCoordinates(tree.c[i], treeData.children[i]) |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getSize(treeData, box = null) { |
|
const { x, y, width, height } = treeData |
|
if (box === null) { |
|
box = { left: x, right: x + width, top: y, bottom: y + height } |
|
} |
|
box.left = Math.min(box.left, x) |
|
box.right = Math.max(box.right, x + width) |
|
box.top = Math.min(box.top, y) |
|
box.bottom = Math.max(box.bottom, y + height) |
|
|
|
if (treeData.children) { |
|
for (const child of treeData.children) { |
|
this.getSize(child, box) |
|
} |
|
} |
|
|
|
return box |
|
} |
|
|
|
|
|
|
|
|
|
assignLayout(tree, treeData, box = null) { |
|
const { x, y } = this.bb.removeBoundingBox(tree.x, tree.y) |
|
treeData.x = x |
|
treeData.y = y |
|
|
|
const { width, height } = treeData |
|
if (box === null) { |
|
box = { left: x, right: x + width, top: y, bottom: y + height } |
|
} |
|
box.left = Math.min(box.left, x) |
|
box.right = Math.max(box.right, x + width) |
|
box.top = Math.min(box.top, y) |
|
box.bottom = Math.max(box.bottom, y + height) |
|
|
|
for (let i = 0; i < tree.c.length; i++) { |
|
this.assignLayout(tree.c[i], treeData.children[i], box) |
|
} |
|
|
|
return { result: treeData, boundingBox: box } |
|
} |
|
} |
|
|
|
export { Layout, BoundingBox } |
|
|