aboutsummaryrefslogtreecommitdiff
path: root/Map/Presentation/Complex Components
diff options
context:
space:
mode:
Diffstat (limited to 'Map/Presentation/Complex Components')
-rw-r--r--Map/Presentation/Complex Components/MapRender/MapRenderView.swift77
1 files changed, 71 insertions, 6 deletions
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))
}
}