TDKCandidates // Optimize the horizontal layout.
This commit is contained in:
parent
0c50046426
commit
f8d79b0e2e
|
@ -140,6 +140,10 @@ public class CandidateCellData: Hashable {
|
|||
}
|
||||
return result.charDescriptions.joined(separator: "\n")
|
||||
}
|
||||
|
||||
public var minWidthToDrawInSwiftUI: Double {
|
||||
Double(cellLength) + ((displayedText.count > 2) ? 0 : fontSizeKey + 0) + ceil(fontSizeCandidate * 0.4)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Contents specifically made for macOS 12 and newer.
|
||||
|
@ -165,7 +169,7 @@ extension CandidateCellData {
|
|||
.foregroundColor(.init(nsColor: fontColorCandidate)).lineLimit(1)
|
||||
}
|
||||
}.padding(3)
|
||||
}
|
||||
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
|
||||
}.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
return result
|
||||
|
@ -202,7 +206,7 @@ extension CandidateCellData {
|
|||
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
|
||||
.foregroundColor(Color(white: 1)).lineLimit(1)
|
||||
}.padding(3).foregroundColor(Color(white: 0.9))
|
||||
}
|
||||
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
|
||||
} else {
|
||||
VStack(spacing: 0) {
|
||||
HStack(spacing: 4) {
|
||||
|
@ -212,7 +216,7 @@ extension CandidateCellData {
|
|||
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
|
||||
.foregroundColor(Color.primary).lineLimit(1)
|
||||
}.padding(3).foregroundColor(Color(white: 0.9))
|
||||
}
|
||||
}.frame(minWidth: minWidthToDrawInSwiftUI, alignment: .leading)
|
||||
}
|
||||
}.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,8 @@ public struct CandidatePool {
|
|||
|
||||
public var maxRowWidth: Int { Int(Double(maxRowCapacity + 3) * 2) * Int(ceil(CandidateCellData.unifiedSize)) }
|
||||
public var maxWindowWidth: Double {
|
||||
ceil(Double(maxRowCapacity + 3) * 2.7 * ceil(CandidateCellData.unifiedSize) * 1.2)
|
||||
let testCell = CandidateCellData(key: "XX", displayedText: "XX", isSelected: false)
|
||||
return Double(maxRowCapacity) * (testCell.minWidthToDrawInSwiftUI + ceil(CandidateCellData.unifiedSize * 0.5))
|
||||
}
|
||||
|
||||
public var currentLineNumber: Int {
|
||||
|
@ -158,7 +159,7 @@ public struct CandidatePool {
|
|||
for (i, candidate) in candidateDataAll.enumerated() {
|
||||
candidate.index = i
|
||||
candidate.whichRow = candidateRows.count
|
||||
let isOverflown: Bool = currentRow.map(\.cellLength).reduce(0, +) + candidate.cellLength > maxRowWidth
|
||||
let isOverflown: Bool = currentRow.map(\.cellLength).reduce(0, +) > maxRowWidth
|
||||
if isOverflown || currentRow.count == maxRowCapacity, !currentRow.isEmpty {
|
||||
candidateRows.append(currentRow)
|
||||
currentRow.removeAll()
|
||||
|
|
|
@ -15,11 +15,11 @@ import SwiftUI
|
|||
@available(macOS 12, *)
|
||||
struct CandidatePoolViewUIHorizontal_Previews: PreviewProvider {
|
||||
@State static var testCandidates: [String] = [
|
||||
"八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "八月", "中秋",
|
||||
"二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗",
|
||||
"🐂🍺🐂🍺", "🐃🍺", "🐂🍺", "🐃🐂🍺🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺",
|
||||
"山林", "風吹", "大地", "草枝", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺",
|
||||
"迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味",
|
||||
"深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗",
|
||||
"嗯", "哼", "啊",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
|
@ -62,14 +62,14 @@ public struct VwrCandidateHorizontal: View {
|
|||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 1.6) {
|
||||
ForEach(thePool.rangeForCurrentPage, id: \.self) { rowIndex in
|
||||
HStack(spacing: 10) {
|
||||
HStack(spacing: ceil(CandidateCellData.unifiedSize * 0.35)) {
|
||||
ForEach(Array(thePool.candidateLines[rowIndex]), id: \.self) { currentCandidate in
|
||||
currentCandidate.attributedStringForSwiftUI.fixedSize()
|
||||
.contentShape(Rectangle())
|
||||
.frame(
|
||||
maxWidth: .infinity,
|
||||
alignment: .topLeading
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { didSelectCandidateAt(currentCandidate.index) }
|
||||
.contextMenu {
|
||||
if controller?.delegate?.isCandidateContextMenuEnabled ?? false {
|
||||
|
@ -91,7 +91,7 @@ public struct VwrCandidateHorizontal: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
Spacer(minLength: Double.infinity)
|
||||
}.frame(
|
||||
minWidth: 0,
|
||||
maxWidth: .infinity,
|
||||
|
@ -103,8 +103,8 @@ public struct VwrCandidateHorizontal: View {
|
|||
ForEach(thePool.rangeForLastPageBlanked, id: \.self) { _ in
|
||||
HStack(spacing: 0) {
|
||||
thePool.blankCell.attributedStringForSwiftUI
|
||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
.contentShape(Rectangle())
|
||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
Spacer()
|
||||
}.frame(
|
||||
minWidth: 0,
|
||||
|
|
|
@ -15,10 +15,11 @@ import SwiftUI
|
|||
@available(macOS 12, *)
|
||||
struct CandidatePoolViewUIVertical_Previews: PreviewProvider {
|
||||
@State static var testCandidates: [String] = [
|
||||
"八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "🐂🍺", "🐃🍺", "八月", "中秋",
|
||||
"山林", "風吹", "大地", "草枝", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺",
|
||||
"二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗",
|
||||
"🐂🍺🐂🍺", "🐃🍺", "🐂🍺", "🐃🐂🍺🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺",
|
||||
"迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味",
|
||||
"深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗",
|
||||
"嗯", "哼", "啊",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
var result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
|
|
|
@ -16,11 +16,11 @@ import SwiftUIBackports
|
|||
@available(macOS 10.15, *)
|
||||
struct CandidatePoolViewUIHorizontalBackports_Previews: PreviewProvider {
|
||||
@State static var testCandidates: [String] = [
|
||||
"八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "八月", "中秋",
|
||||
"二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗",
|
||||
"🐂🍺🐂🍺", "🐃🍺", "🐂🍺", "🐃🐂🍺🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺",
|
||||
"山林", "風吹", "大地", "草枝", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺",
|
||||
"迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味",
|
||||
"深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗",
|
||||
"嗯", "哼", "啊",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
var result = CandidatePool(candidates: testCandidates, rowCapacity: 6)
|
||||
|
@ -63,14 +63,14 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(alignment: .leading, spacing: 1.6) {
|
||||
ForEach(thePool.rangeForCurrentPage, id: \.self) { rowIndex in
|
||||
HStack(spacing: 10) {
|
||||
HStack(spacing: ceil(CandidateCellData.unifiedSize * 0.35)) {
|
||||
ForEach(Array(thePool.candidateLines[rowIndex]), id: \.self) { currentCandidate in
|
||||
currentCandidate.attributedStringForSwiftUIBackports.fixedSize()
|
||||
.contentShape(Rectangle())
|
||||
.frame(
|
||||
maxWidth: .infinity,
|
||||
alignment: .topLeading
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { didSelectCandidateAt(currentCandidate.index) }
|
||||
.contextMenu {
|
||||
if controller?.delegate?.isCandidateContextMenuEnabled ?? false {
|
||||
|
@ -92,7 +92,7 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
Spacer(minLength: Double.infinity)
|
||||
}.frame(
|
||||
minWidth: 0,
|
||||
maxWidth: .infinity,
|
||||
|
@ -104,8 +104,8 @@ public struct VwrCandidateHorizontalBackports: View {
|
|||
ForEach(thePool.rangeForLastPageBlanked, id: \.self) { _ in
|
||||
HStack(spacing: 0) {
|
||||
thePool.blankCell.attributedStringForSwiftUIBackports
|
||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
.contentShape(Rectangle())
|
||||
.frame(maxWidth: .infinity, alignment: .topLeading)
|
||||
Spacer()
|
||||
}.frame(
|
||||
minWidth: 0,
|
||||
|
|
|
@ -16,10 +16,11 @@ import SwiftUIBackports
|
|||
@available(macOS 10.15, *)
|
||||
struct CandidatePoolViewUIVerticalBackports_Previews: PreviewProvider {
|
||||
@State static var testCandidates: [String] = [
|
||||
"八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "🐂🍺", "🐃🍺", "八月", "中秋",
|
||||
"山林", "風吹", "大地", "草枝", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺", "八", "月", "中", "秋", "山", "林", "涼", "風",
|
||||
"吹", "大", "地", "草", "枝", "擺",
|
||||
"二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗",
|
||||
"🐂🍺🐂🍺", "🐃🍺", "🐂🍺", "🐃🐂🍺🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺", "🐂🍺", "🐃🍺",
|
||||
"迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味",
|
||||
"深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗",
|
||||
"嗯", "哼", "啊",
|
||||
]
|
||||
static var thePool: CandidatePool {
|
||||
var result = CandidatePool(candidates: testCandidates, columnCapacity: 6, selectionKeys: "123456789")
|
||||
|
|
|
@ -13,9 +13,10 @@ import XCTest
|
|||
|
||||
final class CandidatePoolTests: XCTestCase {
|
||||
let testCandidates: [String] = [
|
||||
"八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "八月", "中秋",
|
||||
"山林", "風吹", "大地", "草枝", "涼", "擺", "涼", "擺", "涼", "擺", "涼", "擺",
|
||||
"涼", "擺", "擺", "涼",
|
||||
"二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗",
|
||||
"迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味",
|
||||
"深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗",
|
||||
"嗯", "哼", "啊",
|
||||
]
|
||||
|
||||
func testPoolHorizontal() throws {
|
||||
|
|
Loading…
Reference in New Issue