diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-07 21:52:16 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-07 21:52:16 +0200 |
| commit | 129bca332b68bd6106079f58bd0de77baf21ec68 (patch) | |
| tree | e77fc44ca4a5a9a0cb9b653859d7546154472911 /Map/Presentation | |
| parent | 9cbc1f2bf737e862a01c6859029c3683d6067def (diff) | |
Take Notes into account in smart labels
Diffstat (limited to 'Map/Presentation')
3 files changed, 83 insertions, 12 deletions
diff --git a/Map/Presentation/Base Components/MapRender/MapMask.swift b/Map/Presentation/Base Components/MapRender/MapMask.swift index 2c064b3..b477c0a 100644 --- a/Map/Presentation/Base Components/MapRender/MapMask.swift +++ b/Map/Presentation/Base Components/MapRender/MapMask.swift @@ -19,6 +19,7 @@ struct MapMask: View { let mapSize: CGSize let vertexSize: CGSize let vertices: [Vertex] + let labelPositions: [Int: CGPoint] let padding = CGFloat(5.0) var body: some View { @@ -36,8 +37,9 @@ struct MapMask: View { .clipShape(Capsule()) .offset( CGSize( - width: w(vertex.position.x) + vertexSize.width + padding, - height: h(vertex.position.y) + 7.0) + width: labelPositions[vertex.id]?.x + ?? (w(vertex.position.x) + vertexSize.width + padding), + height: labelPositions[vertex.id]?.y ?? (h(vertex.position.y) + 7.0)) ) .blendMode(.destinationOut) }.zIndex(1) @@ -64,5 +66,6 @@ struct MapMask: View { Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square), Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle), Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x), - ]) + ], + labelPositions: [:]) } diff --git a/Map/Presentation/Base Components/MapRender/MapVertices.swift b/Map/Presentation/Base Components/MapRender/MapVertices.swift index f03bb79..e6617b3 100644 --- a/Map/Presentation/Base Components/MapRender/MapVertices.swift +++ b/Map/Presentation/Base Components/MapRender/MapVertices.swift @@ -19,6 +19,7 @@ struct MapVertices: View { let mapSize: CGSize let vertexSize: CGSize let vertices: [Vertex] + let labelPositions: [Int: CGPoint] let padding = CGFloat(5.0) var onDragVertex: (Vertex, CGFloat, CGFloat) -> Void = { _, _, _ in } @@ -36,8 +37,9 @@ struct MapVertices: View { .foregroundColor(.Theme.Map.labelColor) .offset( CGSize( - width: w(vertex.position.x) + vertexSize.width + padding, - height: h(vertex.position.y) + 7.0)) + 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 @@ -113,5 +115,6 @@ struct MapVertices: View { Vertex(id: 1, label: "A Square", position: CGPoint(x: 10.0, y: 20.0), shape: .square), Vertex(id: 2, label: "A triangle", position: CGPoint(x: 25, y: 32.0), shape: .triangle), Vertex(id: 3, label: "An X", position: CGPoint(x: 70.0, y: 70.0), shape: .x), - ]) + ], + labelPositions: [:]) } diff --git a/Map/Presentation/Complex Components/MapRender/MapRenderView.swift b/Map/Presentation/Complex Components/MapRender/MapRenderView.swift index 3b97945..896fbd0 100644 --- a/Map/Presentation/Complex Components/MapRender/MapRenderView.swift +++ b/Map/Presentation/Complex Components/MapRender/MapRenderView.swift @@ -24,14 +24,13 @@ struct MapRenderView: View { @AppStorage("showMapBackground") var showMapBackground: Bool = true @AppStorage("useCustomFont") var useCustomFont: Bool = false @AppStorage("customFontName") var customFontName: String = "Helvetica" - var stage: Stage { Stage.stages(evolution) } - var parsedMap: ParsedMap { - MapParser.parse(content: document.text) - } + @State private var parsedMap: ParsedMap = ParsedMap.empty + @State private var smartLabelPositions: [Int: CGPoint] = [:] + @State private var parseTask: Task<Void, Never>? let mapSize = Dimensions.Map.size let padding = Dimensions.Map.padding @@ -41,6 +40,54 @@ struct MapRenderView: View { var onDragVertex: (Vertex, CGFloat, CGFloat) -> Void = { _, _, _ in } + private func parseMapInBackground() { + parseTask?.cancel() + let currentText = document.text + + parseTask = Task { + // Parse on background thread + let parsed = await Task.detached(priority: .userInitiated) { + MapParser.parse(content: currentText) + }.value + + // Calculate smart positions on background thread + let positions = await Task.detached(priority: .userInitiated) { + var positions: [Int: CGPoint] = [:] + + let axisLines = [ + Line(start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: mapSize.height)), + Line( + start: CGPoint(x: 0, y: mapSize.height), + end: CGPoint(x: mapSize.width, y: mapSize.height)), + ] + + for vertex in parsed.vertices { + positions[vertex.id] = SmartLabelPositioning.calculateOptimalLabelPosition( + for: vertex, + mapSize: mapSize, + vertexSize: vertexSize, + edges: parsed.edges, + opportunities: parsed.opportunities, + inertias: parsed.inertias, + axisLines: axisLines, + allVertices: parsed.vertices, + notes: parsed.notes + ) + } + + return positions + }.value + + // Update UI on main thread + if !Task.isCancelled { + await MainActor.run { + parsedMap = parsed + smartLabelPositions = positions + } + } + } + } + var body: some View { ZStack(alignment: .topLeading) { @@ -68,11 +115,12 @@ struct MapRenderView: View { MapIntertias(mapSize: mapSize, vertexSize: vertexSize, inertias: parsedMap.inertias) }.mask { MapMask( - mapSize: mapSize, vertexSize: vertexSize, vertices: parsedMap.vertices) + mapSize: mapSize, vertexSize: vertexSize, vertices: parsedMap.vertices, + labelPositions: smartLabelPositions) } MapVertices( mapSize: mapSize, vertexSize: vertexSize, vertices: parsedMap.vertices, - onDragVertex: onDragVertex) + labelPositions: smartLabelPositions, onDragVertex: onDragVertex) MapGroups(mapSize: mapSize, vertexSize: vertexSize, groups: parsedMap.groups).drawingGroup( opaque: true ).opacity(0.1) @@ -84,6 +132,23 @@ struct MapRenderView: View { width: mapSize.width + 2 * padding, height: mapSize.height + 2 * padding, alignment: .topLeading ) + .onAppear { + parseMapInBackground() + } + .onChange(of: document.text) { _, _ in + parseMapInBackground() + } + .onDisappear { + parseTask?.cancel() + } + } + + func h(_ dimension: CGFloat) -> CGFloat { + max(0.0, min(mapSize.height, dimension * mapSize.height / 100.0)) + } + + func w(_ dimension: CGFloat) -> CGFloat { + max(0.0, min(mapSize.width, dimension * mapSize.width / 100.0)) } } |