Skip to content

Commit d8fb280

Browse files
authored
Add initial FocusState support (#34)
* Add FocusState.Binding * Add FocusState implementation * Fix cast compile warning
1 parent 49656a5 commit d8fb280

File tree

4 files changed

+170
-0
lines changed

4 files changed

+170
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//
2+
// FocusState.swift
3+
// OpenSwiftUI
4+
//
5+
// Created by Kyle on 2024/2/1.
6+
// Lastest Version: iOS 15.5
7+
// Status: WIP
8+
// ID: 274D264A38B51DC68ACC48A91353B7D0
9+
10+
@frozen
11+
@propertyWrapper
12+
public struct FocusState<Value>: DynamicProperty where Value: Hashable {
13+
@frozen
14+
@propertyWrapper
15+
public struct Binding {
16+
@OpenSwiftUI.Binding
17+
private var binding: Value
18+
19+
init(binding: OpenSwiftUI.Binding<Value>) {
20+
_binding = binding
21+
}
22+
23+
public var wrappedValue: Value {
24+
get { binding }
25+
nonmutating set { binding = newValue }
26+
}
27+
28+
public var projectedValue: FocusState<Value>.Binding {
29+
self
30+
}
31+
32+
var propertyID: ObjectIdentifier {
33+
if let location = _binding.location as? FocusStoreLocation<Value> {
34+
location.id
35+
} else {
36+
#if canImport(ObjectiveC)
37+
ObjectIdentifier(PrivateType.self)
38+
#else
39+
ObjectIdentifier(unsafeBitCast(0, to: AnyObject.self))
40+
#endif
41+
}
42+
}
43+
44+
private enum PrivateType {}
45+
}
46+
47+
var value: Value
48+
var location: AnyLocation<Value>?
49+
var resetValue: Value
50+
public var wrappedValue: Value {
51+
get {
52+
getValue(forReading: true)
53+
}
54+
nonmutating set {
55+
guard let location else {
56+
return
57+
}
58+
location.set(newValue, transaction: Transaction())
59+
}
60+
}
61+
62+
public var projectedValue: FocusState<Value>.Binding {
63+
let value = getValue(forReading: false)
64+
let binding: OpenSwiftUI.Binding<Value>
65+
if let location {
66+
binding = OpenSwiftUI.Binding(value: value, location: location)
67+
} else {
68+
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.")
69+
binding = .constant(value)
70+
}
71+
return Binding(binding: binding)
72+
}
73+
74+
public static func _makeProperty<V>(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue<V>, fieldOffset: Int, inputs: inout _GraphInputs) {
75+
// TODO
76+
}
77+
78+
public init() where Value == Bool {
79+
value = false
80+
location = nil
81+
resetValue = false
82+
}
83+
84+
public init<T>() where Value == T?, T: Hashable {
85+
value = nil
86+
location = nil
87+
resetValue = nil
88+
}
89+
90+
private func getValue(forReading: Bool) -> Value {
91+
guard let location else {
92+
return value
93+
}
94+
if GraphHost.isUpdating {
95+
if forReading {
96+
location.wasRead = true
97+
}
98+
return value
99+
} else {
100+
return location.get()
101+
}
102+
}
103+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// FIXME
2+
protocol ResponderNode {}
3+
4+
struct FocusStore {
5+
var seed: VersionSeed
6+
var focusedResponders: ContiguousArray<ResponderNode>
7+
var plists: [ObjectIdentifier : PropertyList]
8+
}
9+
10+
// MARK: - FocusStore.Key
11+
12+
extension FocusStore {
13+
struct Key<V: Hashable>: PropertyKey {
14+
static var defaultValue: Entry<V>? { nil }
15+
}
16+
}
17+
18+
// MARK: - FocusStore.Item
19+
extension FocusStore {
20+
struct Entry<Value: Hashable> {
21+
22+
}
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class FocusStoreLocation<A: Hashable>: AnyLocation<A> {
2+
override var wasRead: Bool {
3+
get {
4+
_wasRead
5+
}
6+
set {
7+
_wasRead = newValue
8+
}
9+
}
10+
11+
override func get() -> A {
12+
fatalError("TODO")
13+
}
14+
15+
override func set(_ value: A, transaction: Transaction) {
16+
fatalError("TODO")
17+
}
18+
19+
typealias Value = A
20+
21+
override init() { fatalError() }
22+
23+
var store: FocusStore
24+
weak var host: GraphHost?
25+
var resetValue: A
26+
var focusSeed: VersionSeed
27+
var failedAssignment: (A, VersionSeed)?
28+
var resolvedEntry: FocusStore.Entry<A>?
29+
var resolvedSeed: VersionSeed
30+
var _wasRead: Bool
31+
32+
var id: ObjectIdentifier { ObjectIdentifier(self) }
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// FocusedValueKey.swift
3+
// OpenSwiftUI
4+
//
5+
// Created by Kyle on 2024/2/1.
6+
// Lastest Version: iOS 15.5
7+
// Status: Complete
8+
9+
public protocol FocusedValueKey {
10+
associatedtype Value
11+
}

0 commit comments

Comments
 (0)