mirror of
https://github.com/chriseidhof/TerminalUI.git
synced 2026-02-28 19:08:09 +01:00
52 lines
1.8 KiB
Swift
52 lines
1.8 KiB
Swift
public struct ZStack: BuiltinView {
|
|
public init(alignment: Alignment = .center, children: [BuiltinView]) {
|
|
self.alignment = alignment
|
|
self.children = children
|
|
}
|
|
|
|
var alignment: Alignment = .center
|
|
var children: [BuiltinView]
|
|
@LayoutState var rects: [Rect] = []
|
|
|
|
public func render(context: RenderingContext, size: Size) {
|
|
assert(rects.count == children.count)
|
|
let selfPoint = alignment.point(for: size)
|
|
let actualRects: [Rect] = rects.map {
|
|
var copy = $0
|
|
copy.origin.x += selfPoint.x
|
|
copy.origin.y += selfPoint.y
|
|
return copy
|
|
}
|
|
let minX = actualRects.map { $0.minX }.min() ?? 0
|
|
let maxY = actualRects.map { $0.maxY }.max() ?? size.height
|
|
var c = context
|
|
c.translateBy(Point(x: -minX, y: size.height-maxY))
|
|
for i in children.indices {
|
|
let child = children[i]
|
|
var childC = c
|
|
childC.translateBy(Point(x: actualRects[i].origin.x, y: actualRects[i].origin.y))
|
|
child.render(context: childC, size: rects[i].size)
|
|
}
|
|
}
|
|
|
|
|
|
public func size(for proposed: ProposedSize) -> Size {
|
|
layout(proposed: proposed)
|
|
guard let f = rects.first else { return .zero }
|
|
let union = rects.dropFirst().reduce(f, { $0.union($1) })
|
|
let size = union.size
|
|
layout(proposed: ProposedSize(size))
|
|
return size
|
|
}
|
|
|
|
func layout(proposed: ProposedSize) {
|
|
rects = Array(repeating: .zero, count: children.count)
|
|
for i in children.indices {
|
|
let child = children[i]
|
|
let childSize = child.size(for: proposed)
|
|
let point = alignment.point(for: childSize)
|
|
rects[i] = Rect(origin: Point(x: -point.x, y: -point.y), size: childSize)
|
|
}
|
|
}
|
|
}
|