Skip to content

Commit 9faf0fe

Browse files
committed
Implement View.overlay(content:) modifier
1 parent 9ff90d6 commit 9faf0fe

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
extension View {
2+
public func overlay(@ViewBuilder content: () -> some View) -> some View {
3+
OverlayModifier(content: self, overlay: content())
4+
}
5+
}
6+
7+
struct OverlayModifier<Content: View, Overlay: View>: TypeSafeView {
8+
typealias Children = TupleView2<Content, Overlay>.Children
9+
10+
var body: TupleView2<Content, Overlay>
11+
12+
init(content: Content, overlay: Overlay) {
13+
body = TupleView2(content, overlay)
14+
}
15+
16+
func children<Backend: AppBackend>(
17+
backend: Backend,
18+
snapshots: [ViewGraphSnapshotter.NodeSnapshot]?,
19+
environment: EnvironmentValues
20+
) -> TupleView2<Content, Overlay>.Children {
21+
body.children(
22+
backend: backend,
23+
snapshots: snapshots,
24+
environment: environment
25+
)
26+
}
27+
28+
func layoutableChildren<Backend: AppBackend>(
29+
backend: Backend,
30+
children: TupleView2<Content, Overlay>.Children
31+
) -> [LayoutSystem.LayoutableChild] {
32+
[]
33+
}
34+
35+
func asWidget<Backend: AppBackend>(
36+
_ children: TupleView2<Content, Overlay>.Children, backend: Backend
37+
) -> Backend.Widget {
38+
body.asWidget(children, backend: backend)
39+
}
40+
41+
func update<Backend: AppBackend>(
42+
_ widget: Backend.Widget,
43+
children: TupleView2<Content, Overlay>.Children,
44+
proposedSize: SIMD2<Int>,
45+
environment: EnvironmentValues,
46+
backend: Backend,
47+
dryRun: Bool
48+
) -> ViewUpdateResult {
49+
let contentResult = children.child0.update(
50+
with: body.view0,
51+
proposedSize: proposedSize,
52+
environment: environment,
53+
dryRun: dryRun
54+
)
55+
let contentSize = contentResult.size
56+
let overlayResult = children.child1.update(
57+
with: body.view1,
58+
proposedSize: contentSize.size,
59+
environment: environment,
60+
dryRun: dryRun
61+
)
62+
let overlaySize = overlayResult.size
63+
64+
let frameSize = SIMD2(
65+
max(contentSize.size.x, overlaySize.size.x),
66+
max(contentSize.size.y, overlaySize.size.y)
67+
)
68+
69+
if !dryRun {
70+
let contentPosition = (frameSize &- contentSize.size) / 2
71+
let overlayPosition = (frameSize &- overlaySize.size) / 2
72+
73+
backend.setPosition(ofChildAt: 0, in: widget, to: contentPosition)
74+
backend.setPosition(ofChildAt: 1, in: widget, to: overlayPosition)
75+
76+
backend.setSize(of: widget, to: frameSize)
77+
}
78+
79+
return ViewUpdateResult(
80+
size: ViewSize(
81+
size: frameSize,
82+
idealSize: contentSize.idealSize,
83+
minimumWidth: max(contentSize.minimumWidth, overlaySize.minimumWidth),
84+
minimumHeight: max(contentSize.minimumHeight, overlaySize.minimumHeight),
85+
maximumWidth: min(contentSize.maximumWidth, overlaySize.maximumWidth),
86+
maximumHeight: min(contentSize.maximumHeight, overlaySize.maximumHeight)
87+
),
88+
childResults: [contentResult, overlayResult]
89+
)
90+
}
91+
}

0 commit comments

Comments
 (0)