Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 159 additions & 14 deletions Sources/OpenSwiftUICore/Event/Gesture/GestureDebug.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ package import Foundation
package import OpenAttributeGraphShims
import OpenSwiftUI_SPI

// MARK: - GestureDebug

package enum GestureDebug {
package typealias Properties = ArrayWith2Inline<(String, String)>

package enum Kind {
package enum Kind: Hashable {
case empty
case primitive
case modifier
Expand All @@ -38,19 +40,27 @@ package enum GestureDebug {
package typealias Children = ArrayWith2Inline<GestureDebug.Data>

package var children: GestureDebug.Data.Children {
get { _openSwiftUIUnimplementedFailure() }
set { _openSwiftUIUnimplementedFailure() }
get {
switch childrenBox {
case let .value(children):
children
}
}
set {
childrenBox = .value(newValue)
}
}

package init() {
let box: ChildrenBox = .value(ArrayWith2Inline())
kind = .empty
type = EmptyGesture<()>.self
phase = .failed
attribute = .init()
resetSeed = 0
frame = .zero
properties = .init()
childrenBox = .value([]) // FIXME
childrenBox = box
}

package init(
Expand All @@ -63,12 +73,61 @@ package enum GestureDebug {
frame: CGRect,
properties: GestureDebug.Properties
) {
_openSwiftUIUnimplementedFailure()
let box: ChildrenBox = .value(children)
self.kind = kind
self.type = type
self.phase = phase
self.attribute = AnyOptionalAttribute(attribute)
self.resetSeed = resetSeed
self.frame = frame
self.properties = properties
self.childrenBox = box
}
}

fileprivate struct Value<PhaseValue>: Rule {
var kind: GestureDebug.Kind
var type: any Any.Type
@OptionalAttribute var properties: GestureDebug.Properties?
@Attribute var phase: GesturePhase<PhaseValue>
@Attribute var resetSeed: UInt32
@Attribute var position: ViewOrigin
@Attribute var size: ViewSize
@Attribute var transform: ViewTransform
@OptionalAttribute var debugData1: GestureDebug.Data?
@OptionalAttribute var debugData2: GestureDebug.Data?

var childData: GestureDebug.Data.Children {
switch (debugData1, debugData2) {
case (.none, .none):
GestureDebug.Data.Children()
case let (.some(debugData), .none), let (.none, .some(debugData)):
GestureDebug.Data.Children(debugData)
case let (.some(debugData1), .some(debugData2)):
GestureDebug.Data.Children(debugData1, debugData2)
}
}

var value: GestureDebug.Data {
let origin = transform.convert(.localToSpace(.global), point: position)
let frame = CGRect(origin: origin, size: size.value)
return GestureDebug.Data(
kind: kind,
type: type,
children: childData,
phase: phase.withValue(()),
attribute: $phase.identifier,
resetSeed: resetSeed,
frame: frame,
properties: properties ?? .init()
)
}
}
}

extension GestureDebug.Data: Defaultable {
package typealias Value = GestureDebug.Data

package static let defaultValue: GestureDebug.Data = .init()
}

Expand All @@ -90,6 +149,8 @@ extension Attribute where Value: DebuggableGesturePhase {
}
}

// MARK: - makeDebuggableGesture

extension Gesture {
@inline(__always)
nonisolated package static func makeDebuggableGesture(
Expand All @@ -98,8 +159,7 @@ extension Gesture {
) -> _GestureOutputs<Self.Value> {
var outputs = _makeGesture(gesture: gesture, inputs: inputs)
guard inputs.options.contains(.includeDebugOutput),
// FIXME
!(self is PrimitiveDebuggableGesture) else {
!(self is PrimitiveDebuggableGesture.Type) else {
return outputs
}
outputs.wrapDebugOutputs(Self.self, inputs: inputs)
Expand All @@ -116,8 +176,7 @@ extension GestureModifier {
) -> _GestureOutputs<Self.Value> {
var outputs = _makeGesture(modifier: modifier, inputs: inputs, body: body)
guard inputs.options.contains(.includeDebugOutput),
// FIXME
!(self is PrimitiveDebuggableGesture) else {
!(self is PrimitiveDebuggableGesture.Type) else {
return outputs
}
outputs.wrapDebugOutputs(Self.self, inputs: inputs)
Expand Down Expand Up @@ -164,17 +223,30 @@ extension _GestureOutputs {
)
}

private func reallyWrap<T>(
private mutating func reallyWrap<T>(
_ type: T.Type,
kind: GestureDebug.Kind,
properties: Attribute<GestureDebug.Properties>?,
inputs: _GestureInputs,
data: (Attribute<GestureDebug.Data>?, Attribute<GestureDebug.Data>?)
) {
_openSwiftUIUnimplementedFailure()
debugData = Attribute(GestureDebug.Value<Value>(
kind: kind,
type: type,
properties: OptionalAttribute(properties),
phase: phase,
resetSeed: inputs.resetSeed,
position: inputs.animatedPosition(),
size: inputs.viewInputs.size,
transform: inputs.transform,
debugData1: OptionalAttribute(data.0),
debugData2: OptionalAttribute(data.1)
))
}
}

// MARK: - GesturePhase + descriptionWithoutValue

@_spi(ForOpenSwiftUIOnly)
extension GesturePhase {
package var descriptionWithoutValue: String {
Expand All @@ -187,14 +259,87 @@ extension GesturePhase {
}
}

// MARK: - GestureDebug.Data + printTree [TBA]

extension GestureDebug.Data {
package func printTree() {
_openSwiftUIUnimplementedFailure()
printSubtree(parent: nil, indent: Indent(kind: kind))
}

private typealias Indent = String
private struct Indent {
var text: String
var kind: GestureDebug.Kind

init(_ text: String = "", kind: GestureDebug.Kind = .empty) {
self.text = text
self.kind = kind
}

var linePrefix: String {
switch kind {
case .gesture:
text + "* "
case .combiner:
text + "+ "
default:
text
}
}

var childText: String {
switch kind {
case .gesture:
text + "* "
case .combiner:
text + "| "
default:
text
}
}
}

private func printSubtree(parent: GestureDebug.Data?, indent: Indent) {
_openSwiftUIUnimplementedFailure()
var line = indent.linePrefix
let typeDescription = Metadata(type).description
switch kind {
case .empty:
line += "(empty)"
case .modifier:
line += ".(\(typeDescription))"
default:
line += typeDescription
}
if let attribute = attribute.attribute {
line += " \(attribute.description)"
}
line += " (\(phase.descriptionWithoutValue))"
if resetSeed != 0, parent?.resetSeed != resetSeed {
line += " reset:\(resetSeed)"
}
line += frameDescription(relativeTo: parent)
if !properties.isEmpty {
let items = properties.map { "\($0.0): \($0.1)" }
line += " [\(items.joined(separator: ", "))]"
}
Log.eventDebug(line)

let childIndent = Indent(indent.childText, kind: kind)
for child in children {
child.printSubtree(parent: self, indent: childIndent)
}
}

private func frameDescription(relativeTo parent: GestureDebug.Data?) -> String {
var items: [String] = []
let size = frame.size
if parent?.frame.size != size, size != .zero {
items.append("{\((size.width, size.height))}")
}

let origin = frame.origin
if parent?.frame.origin != origin, origin != .zero {
items.append("@\((origin.x, origin.y))")
}
return items.isEmpty ? "" : " " + items.joined(separator: " ")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ private struct DependentPhase<V>: Rule {
}
}

@_spi(ForOpenSwiftUIOnly)
extension GesturePhase {
func paused() -> GesturePhase {
switch self {
Expand Down
Loading
Loading