diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-09 08:34:19 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2025-07-09 08:34:19 +0200 |
| commit | 1ec7f2c6deb64f5b13b32fae2bf74ae2d8aaaabb (patch) | |
| tree | 47b6addedf0bdb18d35774e9b027d07074929d4a /Map/Presentation/Complex Components/MapRender/MapRenderView.swift | |
| parent | 6926feead1a7fadb7f5f974996bef8c30b3bfdbe (diff) | |
Account for CRLF/CR/LF. Lex note text. Use Wmap Parser for renderer.
Diffstat (limited to 'Map/Presentation/Complex Components/MapRender/MapRenderView.swift')
| -rw-r--r-- | Map/Presentation/Complex Components/MapRender/MapRenderView.swift | 152 |
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) ) } |