-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathChunkedText.swift
93 lines (76 loc) · 2.41 KB
/
ChunkedText.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
// ChunkedText.swift
// Ciphers
//
// Created by Arjun B on 13/04/23.
//
import SwiftUI
struct Chunk: Hashable {
let char: String
let id = UUID()
}
struct ChunkedText<Content: View>: View {
let text: String
let limit: Double
let content: (String) -> Content
let charWidth: Double = 18
let charHeight: Double = 18
// space between two consecutive characters
let kerning: Double = 6
// space between lines
let lineSpacing: Double = 6
// number of characters that can fit in a lint
private var lineLength: Int {
if limit == 0 { return 1 }
return Int(limit / (charWidth + kerning))
}
private var chunked: [[Chunk]] {
let lines = text.split(whereSeparator: \.isNewline)
var result = [[Chunk]]()
for line in lines {
let letters = line.map { String($0) }
var rowText = [Chunk]()
var count = 0
for letter in letters {
if count == 0 && letter == " " {
continue
}
count += 1
rowText.append(Chunk(char: letter))
// when line limit is reached
if count % lineLength == 0 {
count = 0
result.append(rowText)
rowText = []
}
}
// if last line was not already added
if count != 0 {
result.append(rowText)
}
}
return result
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
ForEach(chunked, id: \.self) { line in
HStack(spacing: 0) {
ForEach(line, id: \.id) { chunk in
content(chunk.char)
.frame(width: charWidth, height: charHeight)
.padding(.horizontal, kerning/2)
.padding(.vertical, lineSpacing/2)
}
}
}
}
}
}
struct ChunkedText_Previews: PreviewProvider {
static var previews: some View {
ChunkedText(text: "Sphinx of black quartz,\n judge my vow an".uppercased(), limit: 300) { char in
PigpenCharacter(char)
.padding(2)
}
}
}