Skip to content

Commit 737e68c

Browse files
committed
Add typed gesture utility
1 parent 546c381 commit 737e68c

File tree

5 files changed

+29
-22
lines changed

5 files changed

+29
-22
lines changed

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/Lattice.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ struct Lattice: View {
5757
}
5858
.graphOverlay(content: { proxy in
5959
Rectangle().fill(.clear).contentShape(Rectangle())
60-
.withGraphDragGesture(proxy)
60+
.withGraphDragGesture(proxy, of: Int.self)
6161
})
6262
.toolbar {
6363
GraphStateToggle(graphStates: graphStates)

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/MermaidVisualization.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ struct MermaidVisualization: View {
107107
}
108108
.graphOverlay(content: { proxy in
109109
Rectangle().fill(.clear).contentShape(Rectangle())
110-
.withGraphDragGesture(proxy)
110+
.withGraphDragGesture(proxy, of: String.self)
111111
.onTapGesture { value in
112112
if let nodeID = proxy.node(of: String.self, at: value) {
113113
model.tappedNode = nodeID

Examples/ForceDirectedGraphExample/ForceDirectedGraphExample/MyRing.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,17 @@ struct MyRing: View {
5959
}
6060
.graphOverlay { proxy in
6161
Rectangle().fill(.clear).contentShape(Rectangle())
62-
.withGraphDragGesture(proxy, action: describe)
62+
.withGraphDragGesture(proxy, of: Int.self, action: describe)
6363
.withGraphMagnifyGesture(proxy)
6464
}
6565
.toolbar {
6666
GraphStateToggle(graphStates: graphStates)
6767
}
6868
}
6969

70-
func describe(_ state: GraphDragState?) {
70+
func describe(_ state: GraphDragState<Int>?) {
7171
switch state {
72-
case .node(let anyHashable):
73-
let id = anyHashable as! Int
72+
case .node(let id):
7473
if draggingNodeID != id {
7574
draggingNodeID = id
7675
print("Dragging \(id)")

Sources/Grape/Gestures/GraphDragGesture.swift

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import ForceSimulation
22
import SwiftUI
33

4-
public enum GraphDragState {
5-
case node(AnyHashable)
6-
case background(start: SIMD2<Double>)
4+
public enum GraphDragState<NodeID: Hashable> {
5+
case node(NodeID)
6+
case background(SIMD2<Double>)
77
}
88

99
#if !os(tvOS)
1010

1111
@usableFromInline
12-
struct GraphDragModifier: ViewModifier {
12+
struct GraphDragModifier<NodeID: Hashable>: ViewModifier {
1313

1414
@inlinable
1515
public var dragGesture: some Gesture {
@@ -28,18 +28,18 @@ struct GraphDragModifier: ViewModifier {
2828

2929
@inlinable
3030
@State
31-
public var dragState: GraphDragState?
31+
public var dragState: GraphDragState<NodeID>?
3232

3333
@usableFromInline
3434
let graphProxy: GraphProxy
3535

3636
@usableFromInline
37-
let action: ((GraphDragState?) -> Void)?
37+
let action: ((GraphDragState<NodeID>?) -> Void)?
3838

3939
@inlinable
4040
init(
4141
graphProxy: GraphProxy,
42-
action: ((GraphDragState?) -> Void)? = nil
42+
action: ((GraphDragState<NodeID>?) -> Void)? = nil
4343
) {
4444
self.graphProxy = graphProxy
4545
self.action = action
@@ -62,7 +62,7 @@ struct GraphDragModifier: ViewModifier {
6262
case .background(let start):
6363
let delta = value.location.simd - start
6464
graphProxy.modelTransform.translate += delta
65-
dragState = .background(start: value.location.simd)
65+
dragState = .background(value.location.simd)
6666
case .none:
6767
break
6868
}
@@ -79,11 +79,11 @@ struct GraphDragModifier: ViewModifier {
7979
value: DragGesture.Value
8080
) {
8181
if dragState == nil {
82-
if let nodeID = graphProxy.node(at: value.startLocation) {
82+
if let nodeID = graphProxy.node(of: NodeID.self, at: value.startLocation) {
8383
dragState = .node(nodeID)
8484
graphProxy.setNodeFixation(nodeID: nodeID, fixation: value.startLocation)
8585
} else {
86-
dragState = .background(start: value.location.simd)
86+
dragState = .background(value.location.simd)
8787
}
8888
} else {
8989
switch dragState {
@@ -92,7 +92,7 @@ struct GraphDragModifier: ViewModifier {
9292
case .background(let start):
9393
let delta = value.location.simd - start
9494
graphProxy.modelTransform.translate += delta
95-
dragState = .background(start: value.location.simd)
95+
dragState = .background(value.location.simd)
9696
case .none:
9797
break
9898
}
@@ -105,10 +105,17 @@ struct GraphDragModifier: ViewModifier {
105105
}
106106

107107
extension View {
108+
109+
/// Attach a drag gesture to an overlay or a background view created with ``SwiftUICore/View/graphOverlay(alignment:content:)``.
110+
/// - Parameters:
111+
/// - proxy: The graph proxy that provides the graph context.
112+
/// - type: The type of the node ID. The drag gesture will look for the node ID of this type.
113+
/// - action: The action to perform when the drag gesture changes.
108114
@inlinable
109-
public func withGraphDragGesture(
115+
public func withGraphDragGesture<NodeID>(
110116
_ proxy: GraphProxy,
111-
action: ((GraphDragState?) -> Void)? = nil
117+
of type: NodeID.Type,
118+
action: ((GraphDragState<NodeID>?) -> Void)? = nil
112119
) -> some View {
113120
self.modifier(GraphDragModifier(graphProxy: proxy, action: action))
114121
}

Sources/Grape/Gestures/GraphTapGesture.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import SwiftUI
33
extension View {
44
@inlinable
55
@available(tvOS, unavailable)
6-
public func withGraphTapGesture(
6+
public func withGraphTapGesture<NodeID: Hashable>(
77
_ proxy: GraphProxy,
8-
action: @escaping (AnyHashable) -> Void
8+
of type: NodeID.Type,
9+
action: @escaping (NodeID) -> Void
910
) -> some View {
1011
self.onTapGesture { value in
11-
if let nodeID = proxy.node(at: .init(x: value.x, y: value.y)) {
12+
if let nodeID = proxy.node(of: type, at: value) {
1213
action(nodeID)
1314
}
1415
}

0 commit comments

Comments
 (0)