Skip to content
Merged
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
9 changes: 0 additions & 9 deletions Sources/OpenSwiftUICore/Event/Event_TODO.swift

This file was deleted.

178 changes: 178 additions & 0 deletions Sources/OpenSwiftUICore/Event/Gesture/AnyGesture.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
//
// AnyGesture.swift
// OpenSwiftUICore
//
// Status: Complete
// ID: 9726BF9F3BA5F571B5F201AD7C8C86F0 (SwiftUICore)

import OpenGraphShims

// MARK: - AnyGesture [6.5.4]

/// A type-erased gesture.
@available(OpenSwiftUI_v1_0, *)
@frozen
public struct AnyGesture<Value>: PrimitiveGesture, Gesture {
fileprivate var storage: AnyGestureStorageBase<Value>

/// Creates an instance from another gesture.
///
/// - Parameter gesture: A gesture that you use to create a new gesture.
public init<T>(_ gesture: T) where Value == T.Value, T: Gesture {
storage = AnyGestureStorage(gesture: gesture)
}

nonisolated public static func _makeGesture(
gesture: _GraphValue<Self>,
inputs: _GestureInputs
) -> _GestureOutputs<Value> {
let outputs: _GestureOutputs<Value> = inputs.makeIndirectOutputs()
let info = Attribute(AnyGestureInfo<Value>(
gesture: gesture.value,
inputs: inputs,
outputs: outputs,
parentSubgraph: Subgraph.current!
))
info.setFlags(.active, mask: .mask)
outputs.setIndirectDependency(info.identifier)
return outputs
}
}

@available(*, unavailable)
extension AnyGesture: Sendable {}

@usableFromInline
class AnyGestureStorageBase<Value> {

fileprivate func matches(_ other: AnyGestureStorageBase<Value>) -> Bool {
preconditionFailure("")
}

fileprivate func makeChild(
uniqueId: UInt32,
container: Attribute<AnyGestureInfo<Value>.Value>,
inputs: _GestureInputs
) -> _GestureOutputs<Value> {
preconditionFailure("")
}

fileprivate func updateChild(context: AnyRuleContext) {
preconditionFailure("")
}
}

@available(*, unavailable)
extension AnyGestureStorageBase: Sendable {}

private final class AnyGestureStorage<G>: AnyGestureStorageBase<G.Value> where G: Gesture {
var gesture: G

init(gesture: G) {
self.gesture = gesture
}

override func matches(_ other: AnyGestureStorageBase<G.Value>) -> Bool {
other is AnyGestureStorage<G>
}

override func makeChild(
uniqueId: UInt32,
container: Attribute<AnyGestureInfo<G.Value>.Value>,
inputs: _GestureInputs
) -> _GestureOutputs<G.Value> {
let child = Attribute(AnyGestureChild<G>(info: container, uniqueId: uniqueId))
return G.makeDebuggableGesture(gesture: _GraphValue(child), inputs: inputs)
}

override func updateChild(context: AnyRuleContext) {
context.unsafeCast(to: G.self).value = gesture
}
}

private struct AnyGestureInfo<V>: StatefulRule {
@Attribute var gesture: AnyGesture<V>
var inputs: _GestureInputs
var outputs: _GestureOutputs<V>
let parentSubgraph: Subgraph
var oldInfo: Value?

struct Value {
var item: AnyGestureStorageBase<V>
var subgraph: Subgraph
var uniqueId: UInt32
}

mutating func updateValue() {
let newInfo: Value
if let oldInfo, oldInfo.item.matches(gesture.storage) {
newInfo = Value(item: gesture.storage, subgraph: oldInfo.subgraph, uniqueId: oldInfo.uniqueId)
} else {
let uniqueId: UInt32
if let oldInfo {
eraseItem(info: oldInfo)
uniqueId = oldInfo.uniqueId &+ 1
} else {
uniqueId = 0
}
newInfo = makeItem(gesture.storage, uniqueId: uniqueId)
}
value = newInfo
oldInfo = newInfo
}

func makeItem(
_ storage: AnyGestureStorageBase<V>,
uniqueId: UInt32
) -> Value {
let childGraph = Subgraph(graph: parentSubgraph.graph)
parentSubgraph.addChild(childGraph)
return childGraph.apply {
var childInputs = inputs
childInputs.copyCaches()
childInputs.resetSeed = Attribute(AnyResetSeed<V>(
resetSeed: inputs.resetSeed,
info: attribute
))
let childOutputs = storage.makeChild(
uniqueId: uniqueId,
container: attribute,
inputs: childInputs
)
outputs.attachIndirectOutputs(childOutputs)
return Value(item: storage, subgraph: childGraph, uniqueId: uniqueId)
}
}

func eraseItem(info: Value) {
outputs.detachIndirectOutputs()
let subgraph = info.subgraph
subgraph.willInvalidate(isInserted: true)
subgraph.invalidate()
}
}

private struct AnyGestureChild<G>: StatefulRule where G: Gesture {
@Attribute var info: AnyGestureInfo<G.Value>.Value
let uniqueId: UInt32

typealias Value = G

func updateValue() {
guard uniqueId == info.uniqueId else {
return
}
info.item.updateChild(context: AnyRuleContext(context))
}
}

private struct AnyResetSeed<V>: Rule {
@Attribute var resetSeed: UInt32
@Attribute var info: AnyGestureInfo<V>.Value

var value: UInt32 {
let resetSeed = resetSeed
let uniqueId = info.uniqueId
return uniqueId &+ resetSeed
}
}
68 changes: 68 additions & 0 deletions Sources/OpenSwiftUICore/Event/Gesture/MapGesture.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//
// MapGesture.swift
// OpenSwiftUICore
//
// Status: Unimplmented
// ID: EA8BFBF553A9179E7F3A85C72F795A9F (SwiftUICore)

package struct MapGesture<From, To>: GestureModifier {
package var body: (GesturePhase<From>) -> GesturePhase<To>

package init(_ body: @escaping (GesturePhase<From>) -> GesturePhase<To>) {
self.body = body
}

package init(_ body: @escaping (From) -> To) {
self.body = { $0.map(body) }
}

package static func _makeGesture(
modifier: _GraphValue<Self>,
inputs: _GestureInputs,
body: (_GestureInputs) -> _GestureOutputs<From>
) -> _GestureOutputs<To> {



// ModifierGesture<Self, <#Content: Gesture#>>.makeDebuggableGesture(
// gesture: modifier[offset: { .of(&$0.body) }],
// inputs: inputs
// )
preconditionFailure("TODO")
}

package typealias BodyValue = From

package typealias Value = To
}

extension Gesture {
package func mapPhase<T>(
_ body: @escaping (GesturePhase<Self.Value>) -> GesturePhase<T>
) -> ModifierGesture<MapGesture<Value, T>, Self> {
modifier(MapGesture(body))
}

public func map<T>(_ body: @escaping (Value) -> T) -> _MapGesture<Self, T> {
preconditionFailure("TODO")
}

package func discrete(_ enabled: Bool = true) -> ModifierGesture<MapGesture<Value, Value>, Self> {
preconditionFailure("TODO")
}
}

@available(OpenSwiftUI_v1_0, *)
public struct _MapGesture<Content, Value>: PrimitiveGesture where Content: Gesture {
public static func _makeGesture(
gesture: _GraphValue<_MapGesture<Content, Value>>,
inputs: _GestureInputs
) -> _GestureOutputs<Value> {
preconditionFailure("TODO")
}

public typealias Body = Never
}

@available(*, unavailable)
extension _MapGesture: Sendable {}
59 changes: 59 additions & 0 deletions Sources/OpenSwiftUICore/Event/Gesture/RepeatGesture.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// RepeatGesture.swift
// OpenSwiftUICore
//
// Status: Unimplmented
// ID: BECD07FC80B4CA0BF429B041392E806A (SwiftUICore)

import OpenGraphShims

// MARK: - RepeatGesture [6.5.4]

extension Gesture {
package func repeatCount(
_ count: Int,
maximumDelay: Double = 0.35
) -> ModifierGesture<RepeatGesture<Value>, Self> {
modifier(RepeatGesture(count: count, maximumDelay: maximumDelay))
}
}

package struct RepeatGesture<Value>: GestureModifier {
package var count: Int
package var maximumDelay: Double

package init(count: Int, maximumDelay: Double = 0.35) {
self.count = count
self.maximumDelay = maximumDelay
}

package static func _makeGesture(
modifier: _GraphValue<RepeatGesture<Value>>,
inputs: _GestureInputs,
body: (_GestureInputs) -> _GestureOutputs<Value>
) -> _GestureOutputs<Value> {
openSwiftUIUnimplementedFailure()
}
}

private struct RepeatPhase<V>: ResettableGestureRule {
@Attribute var modifier: RepeatGesture<V>
@Attribute var phase: GesturePhase<V>
@Attribute var time: Time
@Attribute var resetSeed: UInt32
@Attribute var resetDelta: UInt32
var useGestureGraph: Bool
var deadline: Time?
var index: UInt32
var lastResetSeed: UInt32

typealias PhaseValue = V
typealias Value = GesturePhase<V>

mutating func updateValue() {
guard resetIfNeeded() else {
return
}
openSwiftUIUnimplementedFailure()
}
}