aboutsummaryrefslogtreecommitdiff
path: root/Map/Presentation
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-07-07 21:52:16 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-07-07 21:52:16 +0200
commit129bca332b68bd6106079f58bd0de77baf21ec68 (patch)
treee77fc44ca4a5a9a0cb9b653859d7546154472911 /Map/Presentation
parent9cbc1f2bf737e862a01c6859029c3683d6067def (diff)
Take Notes into account in smart labels
Diffstat (limited to 'Map/Presentation')
-rw-r--r--Map/Presentation/Base Components/MapRender/MapMask.swift9
-rw-r--r--Map/Presentation/Base Components/MapRender/MapVertices.swift9
-rw-r--r--Map/Presentation/Complex Components/MapRender/MapRenderView.swift77
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))
}
}