TDKCandidates // Make CandidatePool into a class, etc.

This commit is contained in:
ShikiSuen 2023-05-30 15:29:43 +08:00
parent fc29b52f8f
commit 682aaf5053
8 changed files with 99 additions and 56 deletions

View File

@ -39,6 +39,23 @@ public class CandidateCellData: Hashable {
: .init(red: 142 / 255, green: 142 / 255, blue: 147 / 255, alpha: 1) : .init(red: 142 / 255, green: 142 / 255, blue: 147 / 255, alpha: 1)
} }
public var hardCopy: CandidateCellData {
let result = CandidateCellData(key: selectionKey, displayedText: displayedText, spanLength: spanLength, isSelected: isHighlighted)
result.visualDimension = visualDimension
result.locale = locale
result.whichLine = whichLine
result.index = index
result.subIndex = subIndex
return result
}
public var cleanCopy: CandidateCellData {
let result = hardCopy
result.isHighlighted = false
result.selectionKey = " "
return result
}
public init( public init(
key: String, displayedText: String, key: String, displayedText: String,
spanLength spanningLength: Int? = nil, isSelected: Bool = false spanLength spanningLength: Int? = nil, isSelected: Bool = false

View File

@ -39,7 +39,7 @@ public extension CandidateCellData {
Text(verbatim: displayedText) Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!)) .font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(Color(white: 1)).lineLimit(1) .foregroundColor(Color(white: 1)).lineLimit(1)
}.padding(3).foregroundColor(Color(white: 0.9)) }.padding(.vertical, 3).padding(.horizontal, 5)
}.frame(alignment: .leading) }.frame(alignment: .leading)
} else { } else {
VStack(spacing: 0) { VStack(spacing: 0) {
@ -49,7 +49,7 @@ public extension CandidateCellData {
Text(verbatim: displayedText) Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!)) .font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(Color.primary).lineLimit(1) .foregroundColor(Color.primary).lineLimit(1)
}.padding(3).foregroundColor(Color(white: 0.9)) }.padding(.vertical, 3).padding(.horizontal, 5)
}.frame(alignment: .leading) }.frame(alignment: .leading)
} }
}.fixedSize(horizontal: false, vertical: true) }.fixedSize(horizontal: false, vertical: true)
@ -71,7 +71,7 @@ public extension CandidateCellData {
Text(verbatim: displayedText) Text(verbatim: displayedText)
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!)) .font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
.foregroundColor(.init(nsColor: fontColorCandidate)).lineLimit(1) .foregroundColor(.init(nsColor: fontColorCandidate)).lineLimit(1)
}.padding(3) }.padding(.vertical, 3).padding(.horizontal, 5)
}.frame(alignment: .leading) }.frame(alignment: .leading)
}.fixedSize(horizontal: false, vertical: true) }.fixedSize(horizontal: false, vertical: true)
} }

View File

@ -10,13 +10,14 @@ import Foundation
import Shared import Shared
/// ///
public struct CandidatePool { public class CandidatePool {
public let blankCell: CandidateCellData // cell
public let shitCell: CandidateCellData // cell public static let shitCell = CandidateCellData(key: " ", displayedText: "💩", isSelected: false)
public let maxLinesPerPage: Int public static let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
public let layout: LayoutOrientation public private(set) var maxLinesPerPage: Int
public let selectionKeys: String public private(set) var layout: LayoutOrientation
public let candidateDataAll: [CandidateCellData] public private(set) var selectionKeys: String
public private(set) var candidateDataAll: [CandidateCellData]
public var candidateLines: [[CandidateCellData]] = [] public var candidateLines: [[CandidateCellData]] = []
public var tooltip: String = "" public var tooltip: String = ""
public var reverseLookupResult: [String] = [] public var reverseLookupResult: [String] = []
@ -30,7 +31,7 @@ public struct CandidatePool {
/// ///
/// ///
public var maxRowWidth: Double { ceil(Double(maxLineCapacity) * blankCell.cellLength()) } public var maxRowWidth: Double { ceil(Double(maxLineCapacity) * Self.blankCell.cellLength()) }
/// ///
public var currentPositionLabelText: String { public var currentPositionLabelText: String {
@ -79,18 +80,35 @@ public struct CandidatePool {
public init( public init(
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789", candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
layout: LayoutOrientation = .vertical, locale: String = "" layout: LayoutOrientation = .vertical, locale: String = ""
) {
maxLinesPerPage = 1
self.layout = .horizontal
self.selectionKeys = "123456789"
candidateDataAll = []
// compiler
construct(candidates: candidates, lines: lines, selectionKeys: selectionKeys, layout: layout, locale: locale)
}
///
/// - Parameters:
/// - candidates:
/// - selectionKeys:
/// - direction:
/// - locale: zh-Hanszh-Hant
private func construct(
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
layout: LayoutOrientation = .vertical, locale: String = ""
) { ) {
self.layout = layout self.layout = layout
maxLinesPerPage = max(1, lines) maxLinesPerPage = max(1, lines)
blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false) Self.blankCell.locale = locale
shitCell = CandidateCellData(key: " ", displayedText: "💩", isSelected: false)
blankCell.locale = locale
self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys
var allCandidates = candidates.map { var allCandidates = candidates.map {
CandidateCellData(key: " ", displayedText: $0.value, spanLength: $0.keyArray.count) CandidateCellData(key: " ", displayedText: $0.value, spanLength: $0.keyArray.count)
} }
if allCandidates.isEmpty { allCandidates.append(blankCell) } if allCandidates.isEmpty { allCandidates.append(Self.blankCell) }
candidateDataAll = allCandidates candidateDataAll = allCandidates
candidateLines.removeAll()
var currentColumn: [CandidateCellData] = [] var currentColumn: [CandidateCellData] = []
for (i, candidate) in candidateDataAll.enumerated() { for (i, candidate) in candidateDataAll.enumerated() {
candidate.index = i candidate.index = i
@ -127,7 +145,7 @@ public extension CandidatePool {
/// ///
/// - Parameter isBackward: /// - Parameter isBackward:
/// - Returns: /// - Returns:
@discardableResult mutating func flipPage(isBackward: Bool) -> Bool { @discardableResult func flipPage(isBackward: Bool) -> Bool {
backupLineRangeForCurrentPage() backupLineRangeForCurrentPage()
defer { flipLineRangeToNeighborPage(isBackward: isBackward) } defer { flipLineRangeToNeighborPage(isBackward: isBackward) }
return consecutivelyFlipLines(isBackward: isBackward, count: maxLinesPerPage) return consecutivelyFlipLines(isBackward: isBackward, count: maxLinesPerPage)
@ -147,7 +165,7 @@ public extension CandidatePool {
/// - isBackward: /// - isBackward:
/// - count: /// - count:
/// - Returns: /// - Returns:
@discardableResult mutating func consecutivelyFlipLines(isBackward: Bool, count: Int) -> Bool { @discardableResult func consecutivelyFlipLines(isBackward: Bool, count: Int) -> Bool {
switch isBackward { switch isBackward {
case false where currentLineNumber == candidateLines.count - 1: case false where currentLineNumber == candidateLines.count - 1:
return highlightNeighborCandidate(isBackward: false) return highlightNeighborCandidate(isBackward: false)
@ -165,7 +183,7 @@ public extension CandidatePool {
/// ///
/// - Parameter isBackward: /// - Parameter isBackward:
/// - Returns: /// - Returns:
@discardableResult mutating func highlightNeighborCandidate(isBackward: Bool) -> Bool { @discardableResult func highlightNeighborCandidate(isBackward: Bool) -> Bool {
switch isBackward { switch isBackward {
case false where highlightedIndex >= candidateDataAll.count - 1: case false where highlightedIndex >= candidateDataAll.count - 1:
highlight(at: 0) highlight(at: 0)
@ -181,7 +199,7 @@ public extension CandidatePool {
/// ///
/// - Parameter indexSpecified: /// - Parameter indexSpecified:
mutating func highlight(at indexSpecified: Int) { func highlight(at indexSpecified: Int) {
var indexSpecified = indexSpecified var indexSpecified = indexSpecified
let isBackward: Bool = indexSpecified > highlightedIndex let isBackward: Bool = indexSpecified > highlightedIndex
highlightedIndex = indexSpecified highlightedIndex = indexSpecified
@ -222,7 +240,7 @@ public extension CandidatePool {
} }
func cellWidth(_ cell: CandidateCellData) -> (min: CGFloat?, max: CGFloat?) { func cellWidth(_ cell: CandidateCellData) -> (min: CGFloat?, max: CGFloat?) {
let minAccepted = ceil(shitCell.cellLength(isMatrix: false)) let minAccepted = ceil(Self.shitCell.cellLength(isMatrix: false))
let defaultMin: CGFloat = cell.cellLength(isMatrix: maxLinesPerPage != 1) let defaultMin: CGFloat = cell.cellLength(isMatrix: maxLinesPerPage != 1)
var min: CGFloat = defaultMin var min: CGFloat = defaultMin
if layout != .vertical, maxLinesPerPage == 1 { if layout != .vertical, maxLinesPerPage == 1 {
@ -267,14 +285,14 @@ private extension CandidatePool {
max(0, candidateLines.count - maxLinesPerPage) ..< candidateLines.count max(0, candidateLines.count - maxLinesPerPage) ..< candidateLines.count
} }
mutating func selectNewNeighborLine(isBackward: Bool) { func selectNewNeighborLine(isBackward: Bool) {
switch layout { switch layout {
case .horizontal: selectNewNeighborRow(direction: isBackward ? .up : .down) case .horizontal: selectNewNeighborRow(direction: isBackward ? .up : .down)
case .vertical: selectNewNeighborColumn(direction: isBackward ? .left : .right) case .vertical: selectNewNeighborColumn(direction: isBackward ? .left : .right)
} }
} }
mutating func fixLineRange(isBackward: Bool = false) { func fixLineRange(isBackward: Bool = false) {
if !lineRangeForCurrentPage.contains(currentLineNumber) { if !lineRangeForCurrentPage.contains(currentLineNumber) {
switch isBackward { switch isBackward {
case false: case false:
@ -289,11 +307,11 @@ private extension CandidatePool {
} }
} }
mutating func backupLineRangeForCurrentPage() { func backupLineRangeForCurrentPage() {
previouslyRecordedLineRangeForPreviousPage = lineRangeForCurrentPage previouslyRecordedLineRangeForPreviousPage = lineRangeForCurrentPage
} }
mutating func flipLineRangeToNeighborPage(isBackward: Bool = false) { func flipLineRangeToNeighborPage(isBackward: Bool = false) {
guard let prevRange = previouslyRecordedLineRangeForPreviousPage else { return } guard let prevRange = previouslyRecordedLineRangeForPreviousPage else { return }
var lowerBound = prevRange.lowerBound var lowerBound = prevRange.lowerBound
var upperBound = prevRange.upperBound var upperBound = prevRange.upperBound
@ -323,7 +341,7 @@ private extension CandidatePool {
// //
} }
mutating func selectNewNeighborRow(direction: VerticalDirection) { func selectNewNeighborRow(direction: VerticalDirection) {
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
var result = currentSubIndex var result = currentSubIndex
branch: switch direction { branch: switch direction {
@ -369,7 +387,7 @@ private extension CandidatePool {
} }
} }
mutating func selectNewNeighborColumn(direction: HorizontalDirection) { func selectNewNeighborColumn(direction: HorizontalDirection) {
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
switch direction { switch direction {
case .left: case .left:

View File

@ -25,7 +25,7 @@ extension CandidatePool {
private var attributedDescriptionHorizontal: NSAttributedString { private var attributedDescriptionHorizontal: NSAttributedString {
let paragraphStyle = sharedParagraphStyle let paragraphStyle = sharedParagraphStyle
let attrCandidate: [NSAttributedString.Key: AnyObject] = [ let attrCandidate: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFont(size: blankCell.size), .font: Self.blankCell.phraseFont(size: Self.blankCell.size),
.paragraphStyle: paragraphStyle, .paragraphStyle: paragraphStyle,
] ]
let result = NSMutableAttributedString(string: "", attributes: attrCandidate) let result = NSMutableAttributedString(string: "", attributes: attrCandidate)
@ -64,7 +64,7 @@ extension CandidatePool {
private var attributedDescriptionVertical: NSAttributedString { private var attributedDescriptionVertical: NSAttributedString {
let paragraphStyle = sharedParagraphStyle let paragraphStyle = sharedParagraphStyle
let attrCandidate: [NSAttributedString.Key: AnyObject] = [ let attrCandidate: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFont(size: blankCell.size), .font: Self.blankCell.phraseFont(size: Self.blankCell.size),
.paragraphStyle: paragraphStyle, .paragraphStyle: paragraphStyle,
] ]
let result = NSMutableAttributedString(string: "", attributes: attrCandidate) let result = NSMutableAttributedString(string: "", attributes: attrCandidate)
@ -129,7 +129,7 @@ extension CandidatePool {
let positionCounterColorText = NSColor.controlTextColor let positionCounterColorText = NSColor.controlTextColor
let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11) let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11)
let attrPositionCounter: [NSAttributedString.Key: AnyObject] = [ let attrPositionCounter: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFontEmphasized(size: positionCounterTextSize), .font: Self.blankCell.phraseFontEmphasized(size: positionCounterTextSize),
.backgroundColor: positionCounterColorBG, .backgroundColor: positionCounterColorBG,
.foregroundColor: positionCounterColorText, .foregroundColor: positionCounterColorText,
] ]
@ -142,7 +142,7 @@ extension CandidatePool {
private var attributedDescriptionTooltip: NSAttributedString { private var attributedDescriptionTooltip: NSAttributedString {
let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11) let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11)
let attrTooltip: [NSAttributedString.Key: AnyObject] = [ let attrTooltip: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFontEmphasized(size: positionCounterTextSize), .font: Self.blankCell.phraseFontEmphasized(size: positionCounterTextSize),
] ]
let tooltipText = NSAttributedString( let tooltipText = NSAttributedString(
string: " \(tooltip) ", attributes: attrTooltip string: " \(tooltip) ", attributes: attrTooltip
@ -153,10 +153,10 @@ extension CandidatePool {
private var attributedDescriptionReverseLookp: NSAttributedString { private var attributedDescriptionReverseLookp: NSAttributedString {
let reverseLookupTextSize = max(ceil(CandidateCellData.unifiedSize * 0.6), 9) let reverseLookupTextSize = max(ceil(CandidateCellData.unifiedSize * 0.6), 9)
let attrReverseLookup: [NSAttributedString.Key: AnyObject] = [ let attrReverseLookup: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFont(size: reverseLookupTextSize), .font: Self.blankCell.phraseFont(size: reverseLookupTextSize),
] ]
let attrReverseLookupSpacer: [NSAttributedString.Key: AnyObject] = [ let attrReverseLookupSpacer: [NSAttributedString.Key: AnyObject] = [
.font: blankCell.phraseFont(size: reverseLookupTextSize), .font: Self.blankCell.phraseFont(size: reverseLookupTextSize),
] ]
let result = NSMutableAttributedString(string: "", attributes: attrReverseLookupSpacer) let result = NSMutableAttributedString(string: "", attributes: attrReverseLookupSpacer)
for neta in reverseLookupResult { for neta in reverseLookupResult {

View File

@ -31,6 +31,8 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate {
public var useMouseScrolling: Bool = true public var useMouseScrolling: Bool = true
private static var thePool: CandidatePool = .init(candidates: []) private static var thePool: CandidatePool = .init(candidates: [])
private static var currentView: NSView = .init() private static var currentView: NSView = .init()
public static var currentWindow: NSWindow?
public static var currentMenu: NSMenu?
@available(macOS 10.15, *) @available(macOS 10.15, *)
private var theView: some View { private var theView: some View {

View File

@ -66,9 +66,10 @@ public extension VwrCandidateTDKCocoa {
} }
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 { if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
thePool.lineRangeForFinalPageBlanked.enumerated().forEach { _ in thePool.lineRangeForFinalPageBlanked.enumerated().forEach { _ in
var theLine = [thePool.blankCell] var theLine = [CandidateCellData]()
for _ in 1 ..< thePool.maxLineCapacity { let copied = CandidatePool.blankCell.cleanCopy
theLine.append(thePool.blankCell) for _ in 0 ..< thePool.maxLineCapacity {
theLine.append(copied)
} }
let vwrCurrentLine = generateLineContainer(&theLine) let vwrCurrentLine = generateLineContainer(&theLine)
candidateContainer.addView(vwrCurrentLine, in: isVerticalListing ? .top : .leading) candidateContainer.addView(vwrCurrentLine, in: isVerticalListing ? .top : .leading)
@ -88,7 +89,7 @@ public extension VwrCandidateTDKCocoa {
let line = Array(lines[viewLineID]) let line = Array(lines[viewLineID])
columnWidth = line.map(\.visualDimension.width).max() ?? lineDimension.width columnWidth = line.map(\.visualDimension.width).max() ?? lineDimension.width
} else { } else {
columnWidth = thePool.blankCell.visualDimension.width columnWidth = CandidatePool.blankCell.visualDimension.width
} }
accumulatedWidth += columnWidth accumulatedWidth += columnWidth
Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .width, relation: .equal, value: columnWidth) Self.makeSimpleConstraint(item: vwrCurrentLine, attribute: .width, relation: .equal, value: columnWidth)
@ -167,7 +168,7 @@ private extension VwrCandidateTDKCocoa {
} }
private func drawCellCocoa(_ theCell: CandidateCellData? = nil) -> NSView { private func drawCellCocoa(_ theCell: CandidateCellData? = nil) -> NSView {
let theCell = theCell ?? thePool.blankCell let theCell = theCell ?? CandidatePool.blankCell.cleanCopy
let cellLabel = VwrCandidateCell(cell: theCell) let cellLabel = VwrCandidateCell(cell: theCell)
cellLabel.target = self cellLabel.target = self
Self.makeSimpleConstraint(item: cellLabel, attribute: .width, relation: .equal, value: cellLabel.fittingSize.width) Self.makeSimpleConstraint(item: cellLabel, attribute: .width, relation: .equal, value: cellLabel.fittingSize.width)
@ -362,6 +363,7 @@ private extension VwrCandidateTDKCocoa {
} }
theMenu = newMenu theMenu = newMenu
CtlCandidateTDK.currentMenu = newMenu
} }
@objc func menuActionOfBoosting(_: Any? = nil) { @objc func menuActionOfBoosting(_: Any? = nil) {

View File

@ -72,9 +72,10 @@ private extension VwrCandidateTDK {
.id(rowIndex) .id(rowIndex)
} }
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 { if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
let copied = CandidatePool.blankCell.cleanCopy
ForEach(thePool.lineRangeForFinalPageBlanked, id: \.self) { _ in ForEach(thePool.lineRangeForFinalPageBlanked, id: \.self) { _ in
HStack(spacing: 0) { HStack(spacing: 0) {
attributedStringFor(cell: thePool.blankCell) attributedStringFor(cell: copied)
.frame(alignment: .topLeading) .frame(alignment: .topLeading)
.contentShape(Rectangle()) .contentShape(Rectangle())
Spacer() Spacer()
@ -102,8 +103,9 @@ private extension VwrCandidateTDK {
} }
.opacity(columnIndex == thePool.currentLineNumber ? 1 : 0.85) .opacity(columnIndex == thePool.currentLineNumber ? 1 : 0.85)
if thePool.candidateLines[columnIndex].count < thePool.maxLineCapacity { if thePool.candidateLines[columnIndex].count < thePool.maxLineCapacity {
let copied = CandidatePool.blankCell.cleanCopy
ForEach(0 ..< thePool.dummyCellsRequiredForCurrentLine, id: \.self) { _ in ForEach(0 ..< thePool.dummyCellsRequiredForCurrentLine, id: \.self) { _ in
drawCandidate(thePool.blankCell) drawCandidate(copied)
} }
} }
} }
@ -112,17 +114,15 @@ private extension VwrCandidateTDK {
alignment: .topLeading alignment: .topLeading
) )
.id(columnIndex) .id(columnIndex)
if thePool.maxLinesPerPage > 1, thePool.maxLinesPerPage <= loopIndex + 1 {
Spacer(minLength: 0)
}
} }
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 { if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
ForEach(Array(thePool.lineRangeForFinalPageBlanked.enumerated()), id: \.offset) { loopIndex, _ in ForEach(Array(thePool.lineRangeForFinalPageBlanked.enumerated()), id: \.offset) { loopIndex, _ in
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
let copied = CandidatePool.blankCell.cleanCopy
ForEach(0 ..< thePool.maxLineCapacity, id: \.self) { _ in ForEach(0 ..< thePool.maxLineCapacity, id: \.self) { _ in
attributedStringFor(cell: thePool.blankCell).fixedSize() attributedStringFor(cell: copied).fixedSize()
.frame( .frame(
width: ceil(thePool.blankCell.cellLength(isMatrix: true)), width: ceil(CandidatePool.blankCell.cellLength(isMatrix: true)),
alignment: .topLeading alignment: .topLeading
) )
.contentShape(Rectangle()) .contentShape(Rectangle())
@ -132,11 +132,6 @@ private extension VwrCandidateTDK {
maxWidth: .infinity, maxWidth: .infinity,
alignment: .topLeading alignment: .topLeading
) )
if thePool.maxLinesPerPage > 1,
loopIndex >= thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count - 1
{
Spacer(minLength: 0)
}
} }
} }
} }
@ -195,7 +190,7 @@ extension VwrCandidateTDK {
let spacings: CGFloat = horizontalCellSpacing * Double(thePool.maxLineCapacity - 1) let spacings: CGFloat = horizontalCellSpacing * Double(thePool.maxLineCapacity - 1)
let maxWindowWith: CGFloat let maxWindowWith: CGFloat
= ceil( = ceil(
Double(thePool.maxLineCapacity) * (thePool.blankCell.cellLength()) Double(thePool.maxLineCapacity) * (CandidatePool.blankCell.cellLength())
+ spacings + spacings
) )
return thePool.layout == .horizontal && thePool.maxLinesPerPage > 1 ? maxWindowWith : nil return thePool.layout == .horizontal && thePool.maxLinesPerPage > 1 ? maxWindowWith : nil
@ -245,7 +240,7 @@ extension VwrCandidateTDK {
HStack { HStack {
if !tooltip.isEmpty { if !tooltip.isEmpty {
ZStack(alignment: .center) { ZStack(alignment: .center) {
Circle().fill(thePool.blankCell.themeColor.opacity(0.8)) Circle().fill(CandidatePool.blankCell.themeColor.opacity(0.8))
Text(tooltip.first?.description ?? "").padding(2).font(.system(size: CandidateCellData.unifiedSize)) Text(tooltip.first?.description ?? "").padding(2).font(.system(size: CandidateCellData.unifiedSize))
}.frame(width: ceil(CandidateCellData.unifiedSize * 1.7), height: ceil(CandidateCellData.unifiedSize * 1.7)) }.frame(width: ceil(CandidateCellData.unifiedSize * 1.7), height: ceil(CandidateCellData.unifiedSize * 1.7))
} }
@ -371,7 +366,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
] ]
@State static var reverseLookupResult = ["mmmmm", "dddd"] @State static var reverseLookupResult = ["mmmmm", "dddd"]
@State static var tooltip = "📼" @State static var tooltip = "📼"
@State static var oldOS: Bool = true @State static var oldOS: Bool = false
static var testCandidatesConverted: [(keyArray: [String], value: String)] { static var testCandidatesConverted: [(keyArray: [String], value: String)] {
testCandidates.map { candidate in testCandidates.map { candidate in
@ -381,7 +376,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
} }
static var thePoolX: CandidatePool { static var thePoolX: CandidatePool {
var result = CandidatePool( let result = CandidatePool(
candidates: testCandidatesConverted, lines: 4, candidates: testCandidatesConverted, lines: 4,
selectionKeys: "123456", layout: .horizontal selectionKeys: "123456", layout: .horizontal
) )
@ -392,7 +387,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
} }
static var thePoolXS: CandidatePool { static var thePoolXS: CandidatePool {
var result = CandidatePool( let result = CandidatePool(
candidates: testCandidatesConverted, lines: 1, candidates: testCandidatesConverted, lines: 1,
selectionKeys: "123456", layout: .horizontal selectionKeys: "123456", layout: .horizontal
) )
@ -403,7 +398,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
} }
static var thePoolY: CandidatePool { static var thePoolY: CandidatePool {
var result = CandidatePool( let result = CandidatePool(
candidates: testCandidatesConverted, lines: 4, candidates: testCandidatesConverted, lines: 4,
selectionKeys: "123456", layout: .vertical selectionKeys: "123456", layout: .vertical
) )
@ -411,11 +406,12 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
result.tooltip = Self.tooltip result.tooltip = Self.tooltip
result.flipPage(isBackward: false) result.flipPage(isBackward: false)
result.highlight(at: 2) result.highlight(at: 2)
result.highlight(at: 21)
return result return result
} }
static var thePoolYS: CandidatePool { static var thePoolYS: CandidatePool {
var result = CandidatePool( let result = CandidatePool(
candidates: testCandidatesConverted, lines: 1, candidates: testCandidatesConverted, lines: 1,
selectionKeys: "123456", layout: .vertical selectionKeys: "123456", layout: .vertical
) )

View File

@ -273,6 +273,14 @@ public extension SessionCtl {
inputMode = IMEApp.currentInputMode inputMode = IMEApp.currentInputMode
} }
} }
DispatchQueue.main.async {
//
self.candidateUI = nil
CtlCandidateTDK.currentMenu?.cancelTracking()
CtlCandidateTDK.currentMenu = nil
CtlCandidateTDK.currentWindow?.orderOut(nil)
CtlCandidateTDK.currentWindow = nil
}
DispatchQueue.main.async { [self] in DispatchQueue.main.async { [self] in
if isActivated { return } if isActivated { return }