forked from shadowfacts/Tusker
89 lines
2.8 KiB
Swift
89 lines
2.8 KiB
Swift
//
|
|
// BoardView.swift
|
|
// TTTKit
|
|
//
|
|
// Created by Shadowfacts on 12/21/22.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
@available(iOS 16.0, *)
|
|
struct BoardView<Cell: View>: View {
|
|
let board: any Board
|
|
@Binding var cellSize: CGFloat
|
|
let spacing: CGFloat
|
|
let cellProvider: (_ column: Int, _ row: Int) -> Cell
|
|
|
|
init(board: any Board, cellSize: Binding<CGFloat>, spacing: CGFloat, @ViewBuilder cellProvider: @escaping (Int, Int) -> Cell) {
|
|
self.board = board
|
|
self._cellSize = cellSize
|
|
self.spacing = spacing
|
|
self.cellProvider = cellProvider
|
|
}
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
if let win = board.win {
|
|
winOverlay(win)
|
|
}
|
|
|
|
Grid(horizontalSpacing: 10, verticalSpacing: 10) {
|
|
GridRow {
|
|
cellProvider(0, 0)
|
|
.background(GeometryReader { proxy in
|
|
Color.clear
|
|
.preference(key: MarkSizePrefKey.self, value: proxy.size.width)
|
|
.onPreferenceChange(MarkSizePrefKey.self) { newValue in
|
|
cellSize = newValue
|
|
}
|
|
})
|
|
cellProvider(1, 0)
|
|
cellProvider(2, 0)
|
|
}
|
|
GridRow {
|
|
cellProvider(0, 1)
|
|
cellProvider(1, 1)
|
|
cellProvider(2, 1)
|
|
}
|
|
GridRow {
|
|
cellProvider(0, 2)
|
|
cellProvider(1, 2)
|
|
cellProvider(2, 2)
|
|
}
|
|
}
|
|
|
|
let sepOffset = (cellSize + spacing) / 2
|
|
Separator(axis: .vertical)
|
|
.offset(x: -sepOffset)
|
|
Separator(axis: .vertical)
|
|
.offset(x: sepOffset)
|
|
Separator(axis: .horizontal)
|
|
.offset(y: -sepOffset)
|
|
Separator(axis: .horizontal)
|
|
.offset(y: sepOffset)
|
|
}
|
|
.padding(.all, spacing / 2)
|
|
.aspectRatio(1, contentMode: .fit)
|
|
}
|
|
|
|
private func winOverlay(_ win: Win) -> some View {
|
|
let pointsWithIndices = win.points.map { ($0, $0.row * 3 + $0.column) }
|
|
let cellSize = cellSize + spacing
|
|
return ForEach(pointsWithIndices, id: \.1) { (point, _) in
|
|
Rectangle()
|
|
.foregroundColor(Color(UIColor.green))
|
|
.opacity(0.5)
|
|
.frame(width: cellSize, height: cellSize)
|
|
.offset(x: CGFloat(point.column - 1) * cellSize, y: CGFloat(point.row - 1) * cellSize)
|
|
}
|
|
}
|
|
}
|
|
|
|
private struct MarkSizePrefKey: PreferenceKey {
|
|
static var defaultValue: CGFloat = 0
|
|
|
|
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
|
|
value = nextValue()
|
|
}
|
|
}
|