From f8d79b0e2ef2ad0c3d9e0bcd871893216cdcdc2d Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Sun, 5 Feb 2023 14:59:15 +0800 Subject: [PATCH] TDKCandidates // Optimize the horizontal layout. --- .../CandidateWindow/CandidateCellData.swift | 10 +++++++--- .../Sources/CandidateWindow/CandidatePool.swift | 5 +++-- .../VwrCandidateTDK/VwrCandidateHorizontal.swift | 16 ++++++++-------- .../VwrCandidateTDK/VwrCandidateVertical.swift | 9 +++++---- .../VwrCandidateHorizontalBackports.swift | 16 ++++++++-------- .../VwrCandidateVerticalBackports.swift | 9 +++++---- .../CandidatePoolTests.swift | 7 ++++--- 7 files changed, 40 insertions(+), 32 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellData.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellData.swift index 13a22ec5..e0e9e033 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellData.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidateCellData.swift @@ -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) } diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift index 2b15cc3c..d0605cf2 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/CandidatePool.swift @@ -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() diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift index 4489e2e8..c9aafae4 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateHorizontal.swift @@ -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, diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift index 1f6ee71d..a0496c9d 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK/VwrCandidateVertical.swift @@ -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") diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift index 7adf18de..7461c87e 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateHorizontalBackports.swift @@ -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, diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift index d33c1dd8..85cf3780 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/VwrCandidateTDK_Backports/VwrCandidateVerticalBackports.swift @@ -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") diff --git a/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift b/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift index 1331adfb..5e3f0758 100644 --- a/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift +++ b/Packages/vChewing_CandidateWindow/Tests/CandidateWindowTests/CandidatePoolTests.swift @@ -13,9 +13,10 @@ import XCTest final class CandidatePoolTests: XCTestCase { let testCandidates: [String] = [ - "八月中秋山林涼", "八月中秋", "風吹大地", "山林涼", "草枝擺", "八月", "中秋", - "山林", "風吹", "大地", "草枝", "涼", "擺", "涼", "擺", "涼", "擺", "涼", "擺", - "涼", "擺", "擺", "涼", + "二十四歲是學生", "二十四歲", "昏睡紅茶", "食雪漢", "意味深", "學生", "便乗", + "迫真", "驚愕", "論證", "正論", "惱", "悲", "屑", "食", "雪", "漢", "意", "味", + "深", "二", "十", "四", "歲", "是", "學", "生", "昏", "睡", "紅", "茶", "便", "乗", + "嗯", "哼", "啊", ] func testPoolHorizontal() throws {