From 129bca332b68bd6106079f58bd0de77baf21ec68 Mon Sep 17 00:00:00 2001 From: Ruben Beltran del Rio Date: Mon, 7 Jul 2025 21:52:16 +0200 Subject: Take Notes into account in smart labels --- .../MapRender/MapRenderView.swift | 77 ++++++++++++++++++++-- 1 file changed, 71 insertions(+), 6 deletions(-) (limited to 'Map/Presentation/Complex Components/MapRender') 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? 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)) } } -- cgit