diff options
| author | Ruben Beltran del Rio <git@r.bdr.sh> | 2024-09-16 11:10:32 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <git@r.bdr.sh> | 2024-09-16 11:10:32 +0200 |
| commit | e2c37ac1dd2ad562e3d619d39b72a174a2212b67 (patch) | |
| tree | d4da2c0a12db0473eb4030014a92045eebe38834 /Map/Presentation/Base Components/MapRender | |
| parent | fdb4633d3e9158e457d57e820df6e1efb4df39c2 (diff) | |
Map 3 first commit: files, groups and layout
Diffstat (limited to 'Map/Presentation/Base Components/MapRender')
9 files changed, 219 insertions, 87 deletions
diff --git a/Map/Presentation/Base Components/MapRender/MapAxes.swift b/Map/Presentation/Base Components/MapRender/MapAxes.swift index 6ba758f..1b9c226 100644 --- a/Map/Presentation/Base Components/MapRender/MapAxes.swift +++ b/Map/Presentation/Base Components/MapRender/MapAxes.swift @@ -22,10 +22,14 @@ struct MapAxes: View { }.stroke(Color.map.axisColor, lineWidth: lineWidth * 2) // Y Labels - Text("Visible").font(.theme.axisLabel).foregroundColor(.map.labelColor).rotationEffect(Angle(degrees: -90.0)) - .offset(CGSize(width: -35.0, height: 0.0)) - Text("Invisible").font(.theme.axisLabel).foregroundColor(.map.labelColor).rotationEffect(Angle(degrees: -90.0)) - .offset(CGSize(width: -40.0, height: mapSize.height - 20)) + Text("Visible").font(.theme.axisLabel).foregroundColor(.map.labelColor).rotationEffect( + Angle(degrees: -90.0) + ) + .offset(CGSize(width: -35.0, height: 0.0)) + Text("Invisible").font(.theme.axisLabel).foregroundColor(.map.labelColor).rotationEffect( + Angle(degrees: -90.0) + ) + .offset(CGSize(width: -40.0, height: mapSize.height - 20)) // X Labels @@ -71,11 +75,9 @@ struct MapAxes: View { } } -struct MapAxes_Previews: PreviewProvider { - static var previews: some View { - MapAxes( - mapSize: CGSize(width: 200.0, height: 200.0), lineWidth: CGFloat(1.0), - evolution: Stage.stages(.general), stages: [25.0, 50.0, 75.0] - ).padding(50.0) - } +#Preview { + MapAxes( + mapSize: CGSize(width: 200.0, height: 200.0), lineWidth: CGFloat(1.0), + evolution: Stage.stages(.general), stages: [25.0, 50.0, 75.0] + ).padding(50.0) } diff --git a/Map/Presentation/Base Components/MapRender/MapBlockers.swift b/Map/Presentation/Base Components/MapRender/MapBlockers.swift index d943ba8..efd84fa 100644 --- a/Map/Presentation/Base Components/MapRender/MapBlockers.swift +++ b/Map/Presentation/Base Components/MapRender/MapBlockers.swift @@ -31,13 +31,11 @@ struct MapBlockers: View { } } -struct MapBlockers_Previews: PreviewProvider { - static var previews: some View { - MapBlockers( - mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), - blockers: [ - Blocker(id: 0, position: CGPoint(x: 50.0, y: 50.0)), - Blocker(id: 1, position: CGPoint(x: 10.0, y: 20.0)), - ]) - } +#Preview { + MapBlockers( + mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), + blockers: [ + Blocker(id: 0, position: CGPoint(x: 50.0, y: 50.0)), + Blocker(id: 1, position: CGPoint(x: 10.0, y: 20.0)), + ]) } diff --git a/Map/Presentation/Base Components/MapRender/MapEdges.swift b/Map/Presentation/Base Components/MapRender/MapEdges.swift index 3814495..2af7089 100644 --- a/Map/Presentation/Base Components/MapRender/MapEdges.swift +++ b/Map/Presentation/Base Components/MapRender/MapEdges.swift @@ -65,15 +65,13 @@ struct MapEdges: View { } } -struct MapEdges_Previews: PreviewProvider { - static var previews: some View { - MapEdges( - mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, - vertexSize: CGSize(width: 25.0, height: 25.0), - edges: [ - MapEdge( - id: 1, origin: CGPoint(x: 2.0, y: 34.0), destination: CGPoint(x: 23.0, y: 76.2), - arrowhead: true) - ]) - } +#Preview { + MapEdges( + mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, + vertexSize: CGSize(width: 25.0, height: 25.0), + edges: [ + MapEdge( + id: 1, origin: CGPoint(x: 2.0, y: 34.0), destination: CGPoint(x: 23.0, y: 76.2), + arrowhead: true) + ]) } diff --git a/Map/Presentation/Base Components/MapRender/MapGroup.swift b/Map/Presentation/Base Components/MapRender/MapGroup.swift new file mode 100644 index 0000000..9df3338 --- /dev/null +++ b/Map/Presentation/Base Components/MapRender/MapGroup.swift @@ -0,0 +1,83 @@ +import ConcaveHull +import SwiftUI + +struct MapGroup: View { + + let mapSize: CGSize + let vertexSize: CGSize + let group: [Vertex] + let color: Color + + let cornerSize = CGSize(width: 2.0, height: 2.0) + var strokeSize: CGFloat { 1.75 * vertexSize.width } + + var hull: [CGPoint] { + let groupList = group.map({ vertex in + return [Double(vertex.position.x), Double(vertex.position.y)] + }) + let hull = Hull() + let hullPoints = hull.hull(groupList, nil) + return hullPoints.compactMap({ object in + if let point = object as? [Double] { + return CGPoint(x: point[0], y: point[1]) + } + return nil + }) + } + + var body: some View { + Path { path in + var initialMove: CGPoint? + + for point in hull { + let offsetPoint = CGPoint(x: w(point.x), y: h(point.y)) + + if initialMove == nil { + path.move(to: offsetPoint) + initialMove = offsetPoint + } else { + path.addLine(to: offsetPoint) + } + } + + if let initialMove = initialMove { + path.addLine(to: initialMove) + } + + } + .applying( + CGAffineTransform(translationX: vertexSize.width / 2.0, y: vertexSize.height / 2.0) + ) + .fill(color) + .stroke( + color, + style: StrokeStyle( + lineWidth: strokeSize, + lineCap: .round, + lineJoin: .round, + miterLimit: 0, + dash: [], + dashPhase: 0 + ) + ) + } + + 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)) + } +} + +#Preview { + MapGroup( + mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), + group: [ + Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)), + 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), + ], color: .red) +} diff --git a/Map/Presentation/Base Components/MapRender/MapGroups.swift b/Map/Presentation/Base Components/MapRender/MapGroups.swift new file mode 100644 index 0000000..84f7fb2 --- /dev/null +++ b/Map/Presentation/Base Components/MapRender/MapGroups.swift @@ -0,0 +1,32 @@ +import ConcaveHull +import SwiftUI + +struct MapGroups: View { + + let mapSize: CGSize + let vertexSize: CGSize + let groups: [[Vertex]] + + var body: some View { + ForEach(Array(groups.enumerated()), id: \.element) { index, group in + MapGroup(mapSize: mapSize, vertexSize: vertexSize, group: group, color: color(index)) + } + } + + private func color(_ index: Int) -> Color { + return .map.groupColors[index % Color.map.groupColors.count] + } +} + +#Preview { + MapGroups( + mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), + groups: [ + [ + Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)), + 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), + ] + ]) +} diff --git a/Map/Presentation/Base Components/MapRender/MapNotes.swift b/Map/Presentation/Base Components/MapRender/MapNotes.swift index f35b3fe..bbb1aba 100644 --- a/Map/Presentation/Base Components/MapRender/MapNotes.swift +++ b/Map/Presentation/Base Components/MapRender/MapNotes.swift @@ -5,13 +5,12 @@ struct MapNotes: View { let mapSize: CGSize let lineWidth: CGFloat let notes: [Note] - + let maxWidth = 400.0 - var body: some View { ForEach(notes, id: \.id) { note in - Text(note.text.replacingOccurrences(of: "\\n", with: "\n")).font(.theme.axisLabel) + Text(note.text.replacingOccurrences(of: "\\n", with: "\n")).font(.theme.note) .padding(2.0) .background(.white) .foregroundColor(.map.labelColor) @@ -35,12 +34,13 @@ struct MapNotes: View { } } -struct MapNotes_Previews: PreviewProvider { - static var previews: some View { - MapNotes( - mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, - notes: [ - Note(id: 0, position: CGPoint(x: 50.0, y: 50.0), text: "Notes can have a lot more text, so we need to make sure that they're resized correctly"), - ]) - } +#Preview { + MapNotes( + mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, + notes: [ + Note( + id: 0, position: CGPoint(x: 50.0, y: 50.0), + text: + "Notes can have a lot more text, so we need to make sure that they're resized correctly") + ]) } diff --git a/Map/Presentation/Base Components/MapRender/MapOpportunities.swift b/Map/Presentation/Base Components/MapRender/MapOpportunities.swift index 7fcadff..b3051ee 100644 --- a/Map/Presentation/Base Components/MapRender/MapOpportunities.swift +++ b/Map/Presentation/Base Components/MapRender/MapOpportunities.swift @@ -46,7 +46,8 @@ struct MapOpportunities: View { path.closeSubpath() }.applying( CGAffineTransform(translationX: vertexSize.width / 2.0, y: vertexSize.height / 2.0) - ).strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0])).stroke(Color.map.opportunityColor) + ).strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0])).stroke( + Color.map.opportunityColor) } } @@ -59,13 +60,11 @@ struct MapOpportunities: View { } } -struct MapOpportunities_Previews: PreviewProvider { - static var previews: some View { - MapOpportunities( - mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, - vertexSize: CGSize(width: 25.0, height: 25.0), - opportunities: [ - Opportunity(id: 1, origin: CGPoint(x: 2.0, y: 34.0), destination: CGPoint(x: 23.0, y: 76.2)) - ]) - } +#Preview { + MapOpportunities( + mapSize: CGSize(width: 400.0, height: 400.0), lineWidth: 1.0, + vertexSize: CGSize(width: 25.0, height: 25.0), + opportunities: [ + Opportunity(id: 1, origin: CGPoint(x: 2.0, y: 34.0), destination: CGPoint(x: 23.0, y: 76.2)) + ]) } diff --git a/Map/Presentation/Base Components/MapRender/MapStages.swift b/Map/Presentation/Base Components/MapRender/MapStages.swift index 0fc8f48..fc3bfa1 100644 --- a/Map/Presentation/Base Components/MapRender/MapStages.swift +++ b/Map/Presentation/Base Components/MapRender/MapStages.swift @@ -1,5 +1,5 @@ -import SwiftUI import Patterns +import SwiftUI struct MapStages: View { @@ -10,17 +10,29 @@ struct MapStages: View { var body: some View { ZStack(alignment: .topLeading) { - PatternView(design: .constant(.stitch), pixelSize: 1.0, foregroundColor: .map.stageForeground, backgroundColor: .map.stageBackground) - .frame(width: w(stages[0]), height: mapSize.height) - PatternView(design: .constant(.shingles), pixelSize: 1.0, foregroundColor: .map.stageForeground, backgroundColor: .map.stageBackground) - .offset(CGSize(width: w(stages[0]), height: 0)) - .frame(width: w(stages[1]) - w(stages[0]), height: mapSize.height) - PatternView(design: .constant(.shadowGrid), pixelSize: 1.0, foregroundColor: .map.stageForeground, backgroundColor: .map.stageBackground) - .offset(CGSize(width: w(stages[1]), height: 0)) - .frame(width: w(stages[2]) - w(stages[1]), height: mapSize.height) - PatternView(design: .constant(.wicker), pixelSize: 1.0, foregroundColor: .map.stageForeground, backgroundColor: .map.stageBackground) - .offset(CGSize(width: w(stages[2]), height: 0)) - .frame(width: mapSize.width - w(stages[2]), height: mapSize.height) + PatternView( + design: .constant(.stitch), pixelSize: 1.0, foregroundColor: .map.stageForeground, + backgroundColor: .map.stageBackground + ) + .frame(width: w(stages[0]), height: mapSize.height) + PatternView( + design: .constant(.shingles), pixelSize: 1.0, foregroundColor: .map.stageForeground, + backgroundColor: .map.stageBackground + ) + .offset(CGSize(width: w(stages[0]), height: 0)) + .frame(width: w(stages[1]) - w(stages[0]), height: mapSize.height) + PatternView( + design: .constant(.shadowGrid), pixelSize: 1.0, foregroundColor: .map.stageForeground, + backgroundColor: .map.stageBackground + ) + .offset(CGSize(width: w(stages[1]), height: 0)) + .frame(width: w(stages[2]) - w(stages[1]), height: mapSize.height) + PatternView( + design: .constant(.wicker), pixelSize: 1.0, foregroundColor: .map.stageForeground, + backgroundColor: .map.stageBackground + ) + .offset(CGSize(width: w(stages[2]), height: 0)) + .frame(width: mapSize.width - w(stages[2]), height: mapSize.height) Path { path in path.move(to: CGPoint(x: w(stages[0]), y: 0)) @@ -34,7 +46,8 @@ struct MapStages: View { path.closeSubpath() path.move(to: CGPoint(x: w(stages[0]), y: 0)) path.closeSubpath() - }.strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0, 18.0])).stroke(Color.map.axisColor) + }.strokedPath(StrokeStyle(lineWidth: lineWidth / 4, dash: [10.0, 18.0])).stroke( + Color.map.axisColor) } } @@ -43,10 +56,8 @@ struct MapStages: View { } } -struct MapStages_Previews: PreviewProvider { - static var previews: some View { - MapStages( - mapSize: CGSize(width: 200.0, height: 200.0), lineWidth: CGFloat(0.5), - stages: [25.0, 50.0, 75.0]) - } +#Preview { + MapStages( + mapSize: CGSize(width: 200.0, height: 200.0), lineWidth: CGFloat(0.5), + stages: [25.0, 50.0, 75.0]) } diff --git a/Map/Presentation/Base Components/MapRender/MapVertices.swift b/Map/Presentation/Base Components/MapRender/MapVertices.swift index 74cac6d..5bc0a96 100644 --- a/Map/Presentation/Base Components/MapRender/MapVertices.swift +++ b/Map/Presentation/Base Components/MapRender/MapVertices.swift @@ -7,18 +7,29 @@ struct MapVertices: View { let vertices: [Vertex] let padding = CGFloat(5.0) + var onDragVertex: (Vertex, CGFloat, CGFloat) -> Void = { _, _, _ in } + var body: some View { ZStack(alignment: .topLeading) { ForEach(vertices, id: \.id) { vertex in - getVertexShape(vertex).fill(Color.map.vertexColor) - Text(vertex.label.replacingOccurrences(of: "\\n", with: "\n")).font(.theme.vertexLabel) + ZStack(alignment: .topLeading) { + getVertexShape(vertex).fill(Color.map.vertexColor) + Text(vertex.label.replacingOccurrences(of: "\\n", with: "\n")).font(.theme.vertexLabel) .foregroundColor(.map.labelColor) .shadow(color: .white, radius: 0, x: -0.5, y: -0.5) .shadow(color: .white, radius: 0, x: 0.5, y: 0.5) .offset( - CGSize( - width: w(vertex.position.x) + vertexSize.width + padding, - height: h(vertex.position.y) + 7.0)) + CGSize( + width: w(vertex.position.x) + vertexSize.width + padding, + height: h(vertex.position.y) + 7.0)) + }.gesture( + DragGesture() + .onChanged { value in + let deltaX = value.startLocation.x - value.location.x + let deltaY = value.startLocation.y - value.location.y + onDragVertex(vertex, deltaX, deltaY) + } + ) } } } @@ -78,15 +89,13 @@ struct MapVertices: View { } } -struct MapVertices_Previews: PreviewProvider { - static var previews: some View { - MapVertices( - mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), - vertices: [ - Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)), - 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), - ]) - } +#Preview { + MapVertices( + mapSize: CGSize(width: 400.0, height: 400.0), vertexSize: CGSize(width: 25.0, height: 25.0), + vertices: [ + Vertex(id: 0, label: "A Circle", position: CGPoint(x: 50.0, y: 50.0)), + 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), + ]) } |