aboutsummaryrefslogtreecommitdiff
path: root/Map/Presentation/Complex Components/MapRender
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-07-09 08:34:19 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-07-09 08:34:19 +0200
commit1ec7f2c6deb64f5b13b32fae2bf74ae2d8aaaabb (patch)
tree47b6addedf0bdb18d35774e9b027d07074929d4a /Map/Presentation/Complex Components/MapRender
parent6926feead1a7fadb7f5f974996bef8c30b3bfdbe (diff)
Account for CRLF/CR/LF. Lex note text. Use Wmap Parser for renderer.
Diffstat (limited to 'Map/Presentation/Complex Components/MapRender')
-rw-r--r--Map/Presentation/Complex Components/MapRender/MapRenderView.swift152
1 files changed, 143 insertions, 9 deletions
diff --git a/Map/Presentation/Complex Components/MapRender/MapRenderView.swift b/Map/Presentation/Complex Components/MapRender/MapRenderView.swift
index 72a765d..08d1d61 100644
--- a/Map/Presentation/Complex Components/MapRender/MapRenderView.swift
+++ b/Map/Presentation/Complex Components/MapRender/MapRenderView.swift
@@ -19,8 +19,10 @@ import SwiftUI
struct MapRenderView: View {
- @Binding var document: MapDocument
+ var entities: [Wmap.Entity]
@Binding var evolution: StageType
+
+ @State private var lastEntityHash: Int = 0
@AppStorage("showMapBackground") var showMapBackground: Bool = UserPreferences.Defaults
.showMapBackground
@AppStorage("useCustomFont") var useCustomFont: Bool = UserPreferences.Defaults.useCustomFont
@@ -44,14 +46,14 @@ struct MapRenderView: View {
var onDragVertex: (Vertex, CGFloat, CGFloat) -> Void = { _, _, _ in }
- private func parseMapInBackground() {
+ private func convertEntitiesInBackground() {
parseTask?.cancel()
- let currentText = document.text
+ let currentEntities = entities
parseTask = Task {
let parsed = await Task.detached(priority: .userInitiated) {
- MapParser.parse(content: currentText)
+ convertEntitiesToParsedMap(currentEntities)
}.value
let positions = await Task.detached(priority: .userInitiated) {
@@ -92,6 +94,138 @@ struct MapRenderView: View {
}
}
+ private nonisolated func convertEntitiesToParsedMap(_ entities: [Wmap.Entity]) -> ParsedMap {
+ var vertices: [Vertex] = []
+ var edges: [MapEdge] = []
+ var inertias: [Inertia] = []
+ var opportunities: [Opportunity] = []
+ var notes: [Note] = []
+ var stages: [CGFloat] = [25.0, 50.0, 75.0] // default dimensions
+ var groups: [[Vertex]] = []
+
+ // Build a vertex lookup for edges, groups, etc.
+ var vertexMap: [String: Vertex] = [:]
+ var vertexIdCounter = 0
+
+ for entity in entities {
+ switch entity {
+ case .vertex(let vertex):
+ let newVertex = Vertex(
+ id: vertexIdCounter,
+ label: vertex.label,
+ position: CGPoint(x: vertex.coordinates.0, y: vertex.coordinates.1),
+ shape: convertShape(vertex.shape)
+ )
+ vertices.append(newVertex)
+ vertexMap[vertex.label] = newVertex
+ vertexIdCounter += 1
+
+ case .note(let note):
+ notes.append(
+ Note(
+ id: notes.count,
+ position: CGPoint(x: note.coordinates.0, y: note.coordinates.1),
+ text: note.text
+ ))
+
+ case .stage(let stage):
+ let stageIndex = convertStageNumber(stage.number) - 1
+ if stageIndex >= 0 && stageIndex < 3 {
+ stages[stageIndex] = stage.value
+ }
+
+ default:
+ continue
+ }
+ }
+
+ // Second pass for entities that depend on vertices
+ for entity in entities {
+ switch entity {
+ case .edge(let edge):
+ if let fromVertex = vertexMap[edge.from],
+ let toVertex = vertexMap[edge.to]
+ {
+ edges.append(
+ MapEdge(
+ id: edges.count,
+ origin: fromVertex.position,
+ destination: toVertex.position,
+ arrowhead: edge.isDirected
+ ))
+ }
+
+ case .inertia(let inertia):
+ if let vertex = vertexMap[inertia.vertex] {
+ inertias.append(
+ Inertia(
+ id: inertias.count,
+ position: vertex.position
+ ))
+ }
+
+ case .evolution(let evolution):
+ if let vertex = vertexMap[evolution.vertex] {
+ let direction: CGFloat = evolution.isPositive ? 1.0 : -1.0
+ let destination = CGPoint(
+ x: vertex.position.x + (direction * evolution.value),
+ y: vertex.position.y
+ )
+ opportunities.append(
+ Opportunity(
+ id: opportunities.count,
+ origin: vertex.position,
+ destination: destination
+ ))
+ }
+
+ case .group(let group):
+ var groupVertices: [Vertex] = []
+ for vertexName in group.vertices {
+ if let vertex = vertexMap[vertexName] {
+ groupVertices.append(vertex)
+ }
+ }
+ if !groupVertices.isEmpty {
+ groups.append(groupVertices)
+ }
+
+ default:
+ continue
+ }
+ }
+
+ return ParsedMap(
+ vertices: vertices,
+ edges: edges,
+ inertias: inertias,
+ opportunities: opportunities,
+ notes: notes,
+ stages: stages,
+ groups: groups
+ )
+ }
+
+ private nonisolated func convertShape(_ shape: String?) -> VertexShape {
+ guard let shape = shape?.lowercased() else { return .circle }
+ switch shape {
+ case "square": return .square
+ case "triangle": return .triangle
+ case "x": return .x
+ default: return .circle
+ }
+ }
+
+ private nonisolated func convertStageNumber(_ stageNumber: String) -> Int {
+ switch stageNumber.lowercased() {
+ case "i": return 1
+ case "ii": return 2
+ case "iii": return 3
+ case "iv": return 4
+ default: return 1
+ }
+ }
+
var body: some View {
ZStack(alignment: .topLeading) {
@@ -137,13 +271,13 @@ struct MapRenderView: View {
height: mapSize.height + 2 * padding, alignment: .topLeading
)
.onAppear {
- parseMapInBackground()
+ convertEntitiesInBackground()
}
- .onChange(of: document.text) {
- parseMapInBackground()
+ .onChange(of: entities) { _, _ in
+ convertEntitiesInBackground()
}
.onChange(of: useSmartLabelPositioning) {
- parseMapInBackground()
+ convertEntitiesInBackground()
}
.onDisappear {
parseTask?.cancel()
@@ -161,7 +295,7 @@ struct MapRenderView: View {
#Preview {
MapRenderView(
- document: Binding.constant(MapDocument(text: "")),
+ entities: [],
evolution: Binding.constant(StageType.general)
)
}