Skip to content

Commit 7162757

Browse files
committed
Implement fixedSize modifier (with support for only fixing one axis too)
1 parent 9eda12f commit 7162757

File tree

2 files changed

+95
-1
lines changed

2 files changed

+95
-1
lines changed

Sources/SwiftCrossUI/Views/Modifiers/Layout/AspectRatioModifier.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ struct AspectRatioView<Child: View>: TypeSafeView {
9191
)
9292

9393
let childResult = children.child0.update(
94-
with: body.view0,
94+
with: nil,
9595
proposedSize: proposedFrameSize,
9696
environment: environment,
9797
dryRun: dryRun
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
extension View {
2+
public func fixedSize() -> some View {
3+
FixedSizeModifier(self, horizontal: true, vertical: true)
4+
}
5+
6+
public func fixedSize(horizontal: Bool, vertical: Bool) -> some View {
7+
FixedSizeModifier(self, horizontal: horizontal, vertical: vertical)
8+
}
9+
}
10+
11+
struct FixedSizeModifier<Child: View>: TypeSafeView {
12+
var body: TupleView1<Child>
13+
14+
var horizontal: Bool
15+
var vertical: Bool
16+
17+
init(_ child: Child, horizontal: Bool, vertical: Bool) {
18+
body = TupleView1(child)
19+
self.horizontal = horizontal
20+
self.vertical = vertical
21+
}
22+
23+
func children<Backend: AppBackend>(
24+
backend: Backend,
25+
snapshots: [ViewGraphSnapshotter.NodeSnapshot]?,
26+
environment: EnvironmentValues
27+
) -> TupleViewChildren1<Child> {
28+
body.children(backend: backend, snapshots: snapshots, environment: environment)
29+
}
30+
31+
func asWidget<Backend: AppBackend>(
32+
_ children: TupleViewChildren1<Child>,
33+
backend: Backend
34+
) -> Backend.Widget {
35+
let container = backend.createContainer()
36+
backend.addChild(children.child0.widget.into(), to: container)
37+
return container
38+
}
39+
40+
func update<Backend: AppBackend>(
41+
_ widget: Backend.Widget,
42+
children: TupleViewChildren1<Child>,
43+
proposedSize: SIMD2<Int>,
44+
environment: EnvironmentValues,
45+
backend: Backend,
46+
dryRun: Bool
47+
) -> ViewUpdateResult {
48+
let probingChildResult = children.child0.update(
49+
with: body.view0,
50+
proposedSize: proposedSize,
51+
environment: environment,
52+
dryRun: true
53+
)
54+
55+
var frameSize = probingChildResult.size.size
56+
if horizontal && vertical {
57+
frameSize = probingChildResult.size.idealSize
58+
} else if horizontal {
59+
frameSize.x = probingChildResult.size.idealWidthForProposedHeight
60+
} else if vertical {
61+
frameSize.y = probingChildResult.size.idealHeightForProposedWidth
62+
}
63+
64+
let childResult = children.child0.update(
65+
with: body.view0,
66+
proposedSize: frameSize,
67+
environment: environment,
68+
dryRun: dryRun
69+
)
70+
71+
if !dryRun {
72+
let childPosition = Alignment.center.position(
73+
ofChild: childResult.size.size,
74+
in: frameSize
75+
)
76+
backend.setPosition(ofChildAt: 0, in: widget, to: childPosition)
77+
backend.setSize(of: widget, to: frameSize)
78+
}
79+
80+
return ViewUpdateResult(
81+
size: ViewSize(
82+
size: frameSize,
83+
idealSize: childResult.size.idealSize,
84+
idealWidthForProposedHeight: childResult.size.idealWidthForProposedHeight,
85+
idealHeightForProposedWidth: childResult.size.idealHeightForProposedWidth,
86+
minimumWidth: horizontal ? frameSize.x : childResult.size.minimumWidth,
87+
minimumHeight: vertical ? frameSize.y : childResult.size.minimumHeight,
88+
maximumWidth: horizontal ? Double(frameSize.x) : childResult.size.maximumWidth,
89+
maximumHeight: vertical ? Double(frameSize.y) : childResult.size.maximumHeight
90+
),
91+
childResults: [childResult]
92+
)
93+
}
94+
}

0 commit comments

Comments
 (0)