Skip to content

Commit 36baaab

Browse files
committed
Automatic indentation
1 parent 108fe80 commit 36baaab

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

LayoutInspector/DebugLayout.swift

+4-5
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ extension View {
1515
}
1616

1717
/// Monitor the layout proposals and responses for this view and add them to the log.
18-
func debugLayout(_ label: String, indent: Int = 0) -> some View {
19-
DebugLayout(label: label, indent: indent) {
18+
func debugLayout(_ label: String) -> some View {
19+
DebugLayout(label: label) {
2020
self
2121
}
2222
.modifier(DebugLayoutSelectionHighlight(viewID: label))
@@ -26,13 +26,12 @@ extension View {
2626
/// A custom layout that adds the layout proposals and responses for a view to a log for display.
2727
struct DebugLayout: Layout {
2828
var label: String
29-
var indent: Int
3029

3130
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
3231
assert(subviews.count == 1)
33-
logLayoutStep(label, step: .proposal(proposal), indent: indent)
32+
logLayoutStep(label, step: .proposal(proposal))
3433
let response = subviews[0].sizeThatFits(proposal)
35-
logLayoutStep(label, step: .response(response), indent: indent)
34+
logLayoutStep(label, step: .response(response))
3635
return response
3736
}
3837

LayoutInspector/DebugLayoutLog.swift

+32-14
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,39 @@
11
import SwiftUI
22

3-
func logLayoutStep(_ label: String, step: LogItem.Step, indent: Int) {
3+
func logLayoutStep(_ label: String, step: LogItem.Step) {
44
DispatchQueue.main.async {
5-
// Coalesce layout steps if the response follows immediately after the proposal
6-
// for the same view.
7-
//
8-
// In this case, proposal and response can be shown in a single row in the log.
9-
if var lastLogItem = LogStore.shared.log.last,
10-
lastLogItem.label == label,
11-
case .proposal(let proposal) = lastLogItem.step,
12-
case .response(let response) = step
13-
{
5+
guard let prevEntry = LogStore.shared.log.last else {
6+
// First log entry → start at indent 0.
7+
LogStore.shared.log.append(LogItem(label: label, step: step, indent: 0))
8+
return
9+
}
10+
11+
var newEntry = LogItem(label: label, step: step, indent: prevEntry.indent)
12+
let isSameView = prevEntry.label == label
13+
switch (isSameView, prevEntry.step, step) {
14+
case (true, .proposal(let prop), .response(let resp)):
15+
// Response follows immediately after proposal for the same view.
16+
// → We want to display them in a single row.
17+
// → Coalesce both layout steps.
1418
LogStore.shared.log.removeLast()
15-
lastLogItem.step = .proposalAndResponse(proposal: proposal, response: response)
16-
LogStore.shared.log.append(lastLogItem)
17-
} else {
18-
LogStore.shared.log.append(.init(label: label, step: step, indent: indent))
19+
newEntry = prevEntry
20+
newEntry.step = .proposalAndResponse(proposal: prop, response: resp)
21+
LogStore.shared.log.append(newEntry)
22+
23+
case (_, .proposal, .proposal):
24+
// A proposal follows a proposal → nested view → increment indent.
25+
newEntry.indent += 1
26+
LogStore.shared.log.append(newEntry)
27+
28+
case (_, .response, .response),
29+
(_, .proposalAndResponse, .response):
30+
// A response follows a response → last child returns to parent → decrement indent.
31+
newEntry.indent -= 1
32+
LogStore.shared.log.append(newEntry)
33+
34+
default:
35+
// Keep current indentation.
36+
LogStore.shared.log.append(newEntry)
1937
}
2038
}
2139
}

0 commit comments

Comments
 (0)