Skip to content

Commit

Permalink
Add typed gesture utility
Browse files Browse the repository at this point in the history
  • Loading branch information
li3zhen1 committed Jan 9, 2025
1 parent 546c381 commit 737e68c
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ struct Lattice: View {
}
.graphOverlay(content: { proxy in
Rectangle().fill(.clear).contentShape(Rectangle())
.withGraphDragGesture(proxy)
.withGraphDragGesture(proxy, of: Int.self)
})
.toolbar {
GraphStateToggle(graphStates: graphStates)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ struct MermaidVisualization: View {
}
.graphOverlay(content: { proxy in
Rectangle().fill(.clear).contentShape(Rectangle())
.withGraphDragGesture(proxy)
.withGraphDragGesture(proxy, of: String.self)
.onTapGesture { value in
if let nodeID = proxy.node(of: String.self, at: value) {
model.tappedNode = nodeID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,17 @@ struct MyRing: View {
}
.graphOverlay { proxy in
Rectangle().fill(.clear).contentShape(Rectangle())
.withGraphDragGesture(proxy, action: describe)
.withGraphDragGesture(proxy, of: Int.self, action: describe)
.withGraphMagnifyGesture(proxy)
}
.toolbar {
GraphStateToggle(graphStates: graphStates)
}
}

func describe(_ state: GraphDragState?) {
func describe(_ state: GraphDragState<Int>?) {
switch state {
case .node(let anyHashable):
let id = anyHashable as! Int
case .node(let id):
if draggingNodeID != id {
draggingNodeID = id
print("Dragging \(id)")
Expand Down
33 changes: 20 additions & 13 deletions Sources/Grape/Gestures/GraphDragGesture.swift
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import ForceSimulation
import SwiftUI

public enum GraphDragState {
case node(AnyHashable)
case background(start: SIMD2<Double>)
public enum GraphDragState<NodeID: Hashable> {
case node(NodeID)
case background(SIMD2<Double>)
}

#if !os(tvOS)

@usableFromInline
struct GraphDragModifier: ViewModifier {
struct GraphDragModifier<NodeID: Hashable>: ViewModifier {

@inlinable
public var dragGesture: some Gesture {
Expand All @@ -28,18 +28,18 @@ struct GraphDragModifier: ViewModifier {

@inlinable
@State
public var dragState: GraphDragState?
public var dragState: GraphDragState<NodeID>?

@usableFromInline
let graphProxy: GraphProxy

@usableFromInline
let action: ((GraphDragState?) -> Void)?
let action: ((GraphDragState<NodeID>?) -> Void)?

@inlinable
init(
graphProxy: GraphProxy,
action: ((GraphDragState?) -> Void)? = nil
action: ((GraphDragState<NodeID>?) -> Void)? = nil
) {
self.graphProxy = graphProxy
self.action = action
Expand All @@ -62,7 +62,7 @@ struct GraphDragModifier: ViewModifier {
case .background(let start):
let delta = value.location.simd - start
graphProxy.modelTransform.translate += delta
dragState = .background(start: value.location.simd)
dragState = .background(value.location.simd)
case .none:
break
}
Expand All @@ -79,11 +79,11 @@ struct GraphDragModifier: ViewModifier {
value: DragGesture.Value
) {
if dragState == nil {
if let nodeID = graphProxy.node(at: value.startLocation) {
if let nodeID = graphProxy.node(of: NodeID.self, at: value.startLocation) {
dragState = .node(nodeID)
graphProxy.setNodeFixation(nodeID: nodeID, fixation: value.startLocation)
} else {
dragState = .background(start: value.location.simd)
dragState = .background(value.location.simd)
}
} else {
switch dragState {
Expand All @@ -92,7 +92,7 @@ struct GraphDragModifier: ViewModifier {
case .background(let start):
let delta = value.location.simd - start
graphProxy.modelTransform.translate += delta
dragState = .background(start: value.location.simd)
dragState = .background(value.location.simd)
case .none:
break
}
Expand All @@ -105,10 +105,17 @@ struct GraphDragModifier: ViewModifier {
}

extension View {

/// Attach a drag gesture to an overlay or a background view created with ``SwiftUICore/View/graphOverlay(alignment:content:)``.
/// - Parameters:
/// - proxy: The graph proxy that provides the graph context.
/// - type: The type of the node ID. The drag gesture will look for the node ID of this type.
/// - action: The action to perform when the drag gesture changes.
@inlinable
public func withGraphDragGesture(
public func withGraphDragGesture<NodeID>(
_ proxy: GraphProxy,
action: ((GraphDragState?) -> Void)? = nil
of type: NodeID.Type,
action: ((GraphDragState<NodeID>?) -> Void)? = nil
) -> some View {
self.modifier(GraphDragModifier(graphProxy: proxy, action: action))
}
Expand Down
7 changes: 4 additions & 3 deletions Sources/Grape/Gestures/GraphTapGesture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import SwiftUI
extension View {
@inlinable
@available(tvOS, unavailable)
public func withGraphTapGesture(
public func withGraphTapGesture<NodeID: Hashable>(
_ proxy: GraphProxy,
action: @escaping (AnyHashable) -> Void
of type: NodeID.Type,
action: @escaping (NodeID) -> Void
) -> some View {
self.onTapGesture { value in
if let nodeID = proxy.node(at: .init(x: value.x, y: value.y)) {
if let nodeID = proxy.node(of: type, at: value) {
action(nodeID)
}
}
Expand Down

0 comments on commit 737e68c

Please sign in to comment.