Skip to content

Commit d74bfb0

Browse files
committed
Fix ViewGraphNode layout caching; fixes fixedSize (+tests)
1 parent e5f3cbe commit d74bfb0

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

Sources/SwiftCrossUI/ViewGraph/ViewGraphNode.swift

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -226,16 +226,18 @@ public class ViewGraphNode<NodeView: View, Backend: AppBackend> {
226226
// If the view has already been updated this update cycle and claims
227227
// to be fixed size (maximumSize == minimumSize) then reuse the current
228228
// result.
229-
let maximumSize = SIMD2(
230-
currentLayout.size.maximumWidth,
231-
currentLayout.size.maximumHeight
232-
)
233-
let minimumSize = SIMD2(
234-
Double(currentLayout.size.minimumWidth),
235-
Double(currentLayout.size.minimumHeight)
236-
)
237-
if maximumSize == minimumSize {
238-
return currentLayout
229+
if lastProposedSize.concrete != nil && proposedSize.concrete != nil {
230+
let maximumSize = SIMD2(
231+
currentLayout.size.maximumWidth,
232+
currentLayout.size.maximumHeight
233+
)
234+
let minimumSize = SIMD2(
235+
Double(currentLayout.size.minimumWidth),
236+
Double(currentLayout.size.minimumHeight)
237+
)
238+
if maximumSize == minimumSize {
239+
return currentLayout
240+
}
239241
}
240242
}
241243

Tests/SwiftCrossUITests/SwiftCrossUITests.swift

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ final class SwiftCrossUITests: XCTestCase {
8383
)
8484
backend.setChild(ofWindow: window, to: viewGraph.rootNode.widget.into())
8585

86+
// We have to run this twice due to the computeLayout/commit change
87+
// to the View protocol. This should get neater once ViewGraph uses
88+
// computeLayout/commit as well instead of updates with dryRun.
89+
_ = viewGraph.update(
90+
proposedSize: SIMD2(200, 200),
91+
environment: environment,
92+
dryRun: true
93+
)
8694
let result = viewGraph.update(
8795
proposedSize: SIMD2(200, 200),
8896
environment: environment,
@@ -104,6 +112,76 @@ final class SwiftCrossUITests: XCTestCase {
104112
)
105113
}
106114

115+
func testTextLayout() {
116+
let backend = AppKitBackend()
117+
let text = Text("Lorem ipsum dolor sit amet")
118+
let widget = text.asWidget(backend: backend)
119+
let environment = EnvironmentValues(backend: backend)
120+
let children = text.children(backend: backend, snapshots: nil, environment: environment)
121+
let idealLayout = text.computeLayout(
122+
widget,
123+
children: children,
124+
proposedSize: .ideal,
125+
environment: environment,
126+
backend: backend
127+
)
128+
let fixedHeightLayout = text.computeLayout(
129+
widget,
130+
children: children,
131+
proposedSize: SizeProposal(idealLayout.size.size.x / 2, nil),
132+
environment: environment,
133+
backend: backend
134+
)
135+
let layout = text.computeLayout(
136+
widget,
137+
proposedSize: SizeProposal(idealLayout.size.size.x / 2, 1000),
138+
environment: environment,
139+
backend: backend
140+
)
141+
XCTAssert(
142+
idealLayout.size.size.y != fixedHeightLayout.size.size.y,
143+
"Halving text width didn't affect text height"
144+
)
145+
XCTAssertEqual(fixedHeightLayout.size, layout.size, "Excess height changed text size")
146+
}
147+
148+
func testFixedSizeLayout() {
149+
let backend = AppKitBackend()
150+
let text = Text("Lorem ipsum dolor sit amet")
151+
.fixedSize(horizontal: false, vertical: true)
152+
let window = backend.createWindow(withDefaultSize: SIMD2(200, 200))
153+
let environment = EnvironmentValues(backend: backend)
154+
.with(\.window, window)
155+
let children = text.children(backend: backend, snapshots: nil, environment: environment)
156+
let widget = text.asWidget(children, backend: backend)
157+
let idealLayout = text.computeLayout(
158+
widget,
159+
children: children,
160+
proposedSize: .ideal,
161+
environment: environment,
162+
backend: backend
163+
)
164+
let fixedHeightLayout = text.computeLayout(
165+
widget,
166+
children: children,
167+
proposedSize: SizeProposal(idealLayout.size.size.x / 2, nil),
168+
environment: environment,
169+
backend: backend
170+
)
171+
let layout = text.computeLayout(
172+
widget,
173+
children: children,
174+
proposedSize: SizeProposal(idealLayout.size.size.x / 2, 1000),
175+
environment: environment,
176+
backend: backend
177+
)
178+
XCTAssert(
179+
idealLayout.size.size.y != fixedHeightLayout.size.size.y,
180+
"Halving text width didn't affect text height"
181+
)
182+
XCTAssertEqual(fixedHeightLayout.size, layout.size, "Excess height changed text size")
183+
}
184+
107185
static func snapshotView(_ view: NSView) throws -> Data {
108186
view.wantsLayer = true
109187
view.layer?.backgroundColor = CGColor.white

0 commit comments

Comments
 (0)