diff --git a/Sources/OpenSwiftUI/EventHandling/Focus/FocusState.swift b/Sources/OpenSwiftUI/EventHandling/Focus/FocusState.swift new file mode 100644 index 0000000..6649254 --- /dev/null +++ b/Sources/OpenSwiftUI/EventHandling/Focus/FocusState.swift @@ -0,0 +1,103 @@ +// +// FocusState.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/1. +// Lastest Version: iOS 15.5 +// Status: WIP +// ID: 274D264A38B51DC68ACC48A91353B7D0 + +@frozen +@propertyWrapper +public struct FocusState: DynamicProperty where Value: Hashable { + @frozen + @propertyWrapper + public struct Binding { + @OpenSwiftUI.Binding + private var binding: Value + + init(binding: OpenSwiftUI.Binding) { + _binding = binding + } + + public var wrappedValue: Value { + get { binding } + nonmutating set { binding = newValue } + } + + public var projectedValue: FocusState.Binding { + self + } + + var propertyID: ObjectIdentifier { + if let location = _binding.location as? FocusStoreLocation { + location.id + } else { + #if canImport(ObjectiveC) + ObjectIdentifier(PrivateType.self) + #else + ObjectIdentifier(unsafeBitCast(0, to: AnyObject.self)) + #endif + } + } + + private enum PrivateType {} + } + + var value: Value + var location: AnyLocation? + var resetValue: Value + public var wrappedValue: Value { + get { + getValue(forReading: true) + } + nonmutating set { + guard let location else { + return + } + location.set(newValue, transaction: Transaction()) + } + } + + public var projectedValue: FocusState.Binding { + let value = getValue(forReading: false) + let binding: OpenSwiftUI.Binding + if let location { + binding = OpenSwiftUI.Binding(value: value, location: location) + } else { + Log.runtimeIssues("Accessing FocusState's value outside of the body of a View. This will result in a constant Binding of the initial value and will not update.") + binding = .constant(value) + } + return Binding(binding: binding) + } + + public static func _makeProperty(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue, fieldOffset: Int, inputs: inout _GraphInputs) { + // TODO + } + + public init() where Value == Bool { + value = false + location = nil + resetValue = false + } + + public init() where Value == T?, T: Hashable { + value = nil + location = nil + resetValue = nil + } + + private func getValue(forReading: Bool) -> Value { + guard let location else { + return value + } + if GraphHost.isUpdating { + if forReading { + location.wasRead = true + } + return value + } else { + return location.get() + } + } +} diff --git a/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift new file mode 100644 index 0000000..c124349 --- /dev/null +++ b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStore.swift @@ -0,0 +1,23 @@ +// FIXME +protocol ResponderNode {} + +struct FocusStore { + var seed: VersionSeed + var focusedResponders: ContiguousArray + var plists: [ObjectIdentifier : PropertyList] +} + +// MARK: - FocusStore.Key + +extension FocusStore { + struct Key: PropertyKey { + static var defaultValue: Entry? { nil } + } +} + +// MARK: - FocusStore.Item +extension FocusStore { + struct Entry { + + } +} diff --git a/Sources/OpenSwiftUI/EventHandling/Focus/FocusStoreLocation.swift b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStoreLocation.swift new file mode 100644 index 0000000..ab229ad --- /dev/null +++ b/Sources/OpenSwiftUI/EventHandling/Focus/FocusStoreLocation.swift @@ -0,0 +1,33 @@ +class FocusStoreLocation: AnyLocation { + override var wasRead: Bool { + get { + _wasRead + } + set { + _wasRead = newValue + } + } + + override func get() -> A { + fatalError("TODO") + } + + override func set(_ value: A, transaction: Transaction) { + fatalError("TODO") + } + + typealias Value = A + + override init() { fatalError() } + + var store: FocusStore + weak var host: GraphHost? + var resetValue: A + var focusSeed: VersionSeed + var failedAssignment: (A, VersionSeed)? + var resolvedEntry: FocusStore.Entry? + var resolvedSeed: VersionSeed + var _wasRead: Bool + + var id: ObjectIdentifier { ObjectIdentifier(self) } +} diff --git a/Sources/OpenSwiftUI/EventHandling/Focus/FocusedValueKey.swift b/Sources/OpenSwiftUI/EventHandling/Focus/FocusedValueKey.swift new file mode 100644 index 0000000..d8887c2 --- /dev/null +++ b/Sources/OpenSwiftUI/EventHandling/Focus/FocusedValueKey.swift @@ -0,0 +1,11 @@ +// +// FocusedValueKey.swift +// OpenSwiftUI +// +// Created by Kyle on 2024/2/1. +// Lastest Version: iOS 15.5 +// Status: Complete + +public protocol FocusedValueKey { + associatedtype Value +}