diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-08 09:41:13 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-08 09:41:13 +0200 |
| commit | 68c53f41cf165e42f40e12fe724043b014bc9b68 (patch) | |
| tree | 2d26ce8f97a963b4a4a145413765e9fe5cf04a89 | |
| parent | 96a65922a562c59b792704dfae62119f4bf1560f (diff) | |
Add draggong logic to vertices
| -rw-r--r-- | Map/Presentation/Base Components/MapRender/MapVertices.swift | 62 |
1 files changed, 52 insertions, 10 deletions
diff --git a/Map/Presentation/Base Components/MapRender/MapVertices.swift b/Map/Presentation/Base Components/MapRender/MapVertices.swift index e6617b3..8b5dde2 100644 --- a/Map/Presentation/Base Components/MapRender/MapVertices.swift +++ b/Map/Presentation/Base Components/MapRender/MapVertices.swift @@ -22,13 +22,50 @@ struct MapVertices: View { let labelPositions: [Int: CGPoint] let padding = CGFloat(5.0) + @State private var offset = CGSize.zero + @State private var draggingVertex: Vertex? = nil + var onDragVertex: (Vertex, CGFloat, CGFloat) -> Void = { _, _, _ in } var body: some View { ZStack(alignment: .topLeading) { ForEach(vertices, id: \.id) { vertex in ZStack(alignment: .topLeading) { - getVertexShape(vertex).fill(Color.Theme.Map.vertexColor) + getVertexShape(vertex) + .fill(Color.Theme.Map.vertexColor) + .offset( + x: vertex == draggingVertex ? offset.width : 0, + y: vertex == draggingVertex ? offset.height : 0) + + // Drag Hit box. Path bounds seem to be infinite. + Rectangle() + .fill(Color.black.opacity(0.001)) + .frame(width: vertexSize.width, height: vertexSize.height) + .offset(x: w(vertex.position.x), y: h(vertex.position.y)) + .onHover { isHovering in + if isHovering { + NSCursor.pointingHand.set() + } else { + NSCursor.arrow.set() + } + } + .gesture( + DragGesture() + .onChanged { value in + offset = value.translation + draggingVertex = vertex + NSCursor.closedHand.set() + } + .onEnded { value in + let newX = mw(w(vertex.position.x) + value.translation.width) + let newY = mh(h(vertex.position.y) + value.translation.height) + + onDragVertex(vertex, newX, newY) + + NSCursor.arrow.set() + } + ) + Text(vertex.label.replacingOccurrences(of: "\\n", with: "\n")) .font(.Theme.Map.vertexLabel) .lineSpacing( @@ -39,15 +76,12 @@ struct MapVertices: View { CGSize( width: labelPositions[vertex.id]?.x ?? (w(vertex.position.x) + vertexSize.width + padding), - height: labelPositions[vertex.id]?.y ?? (h(vertex.position.y) + 7.0))) - }.gesture( - DragGesture() - .onChanged { value in - let deltaX = value.startLocation.x - value.location.x - let deltaY = value.startLocation.y - value.location.y - onDragVertex(vertex, deltaX, deltaY) - } - ) + height: labelPositions[vertex.id]?.y ?? (h(vertex.position.y) + 7.0)) + ) + .offset( + x: vertex == draggingVertex ? offset.width : 0, + y: vertex == draggingVertex ? offset.height : 0) + } } } } @@ -60,6 +94,14 @@ struct MapVertices: View { max(0.0, min(mapSize.width, dimension * mapSize.width / 100.0)) } + func mh(_ dimension: CGFloat) -> CGFloat { + max(0.0, min(100, dimension * 100 / mapSize.height)) + } + + func mw(_ dimension: CGFloat) -> CGFloat { + max(0.0, min(100, dimension * 100 / mapSize.width)) + } + func getVertexShape(_ vertex: Vertex) -> Path { switch vertex.shape { case .circle: |