TDKCandidates // Make CandidatePool into a class, etc.
This commit is contained in:
parent
fc29b52f8f
commit
682aaf5053
|
@ -39,6 +39,23 @@ public class CandidateCellData: Hashable {
|
|||
: .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(
|
||||
key: String, displayedText: String,
|
||||
spanLength spanningLength: Int? = nil, isSelected: Bool = false
|
||||
|
|
|
@ -39,7 +39,7 @@ public extension CandidateCellData {
|
|||
Text(verbatim: displayedText)
|
||||
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
|
||||
.foregroundColor(Color(white: 1)).lineLimit(1)
|
||||
}.padding(3).foregroundColor(Color(white: 0.9))
|
||||
}.padding(.vertical, 3).padding(.horizontal, 5)
|
||||
}.frame(alignment: .leading)
|
||||
} else {
|
||||
VStack(spacing: 0) {
|
||||
|
@ -49,7 +49,7 @@ public extension CandidateCellData {
|
|||
Text(verbatim: displayedText)
|
||||
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
|
||||
.foregroundColor(Color.primary).lineLimit(1)
|
||||
}.padding(3).foregroundColor(Color(white: 0.9))
|
||||
}.padding(.vertical, 3).padding(.horizontal, 5)
|
||||
}.frame(alignment: .leading)
|
||||
}
|
||||
}.fixedSize(horizontal: false, vertical: true)
|
||||
|
@ -71,7 +71,7 @@ public extension CandidateCellData {
|
|||
Text(verbatim: displayedText)
|
||||
.font(.init(CTFontCreateUIFontForLanguage(.system, fontSizeCandidate, locale as CFString)!))
|
||||
.foregroundColor(.init(nsColor: fontColorCandidate)).lineLimit(1)
|
||||
}.padding(3)
|
||||
}.padding(.vertical, 3).padding(.horizontal, 5)
|
||||
}.frame(alignment: .leading)
|
||||
}.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
|
|
|
@ -10,13 +10,14 @@ import Foundation
|
|||
import Shared
|
||||
|
||||
/// 候選字窗會用到的資料池單位,即用即拋。
|
||||
public struct CandidatePool {
|
||||
public let blankCell: CandidateCellData
|
||||
public let shitCell: CandidateCellData // 只用來測量單漢字候選字 cell 的最大可能寬度。
|
||||
public let maxLinesPerPage: Int
|
||||
public let layout: LayoutOrientation
|
||||
public let selectionKeys: String
|
||||
public let candidateDataAll: [CandidateCellData]
|
||||
public class CandidatePool {
|
||||
// 只用來測量單漢字候選字 cell 的最大可能寬度。
|
||||
public static let shitCell = CandidateCellData(key: " ", displayedText: "💩", isSelected: false)
|
||||
public static let blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
|
||||
public private(set) var maxLinesPerPage: Int
|
||||
public private(set) var layout: LayoutOrientation
|
||||
public private(set) var selectionKeys: String
|
||||
public private(set) var candidateDataAll: [CandidateCellData]
|
||||
public var candidateLines: [[CandidateCellData]] = []
|
||||
public var tooltip: 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 {
|
||||
|
@ -79,18 +80,35 @@ public struct CandidatePool {
|
|||
public init(
|
||||
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
|
||||
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-Hans」或「zh-Hant」。
|
||||
private func construct(
|
||||
candidates: [(keyArray: [String], value: String)], lines: Int = 3, selectionKeys: String = "123456789",
|
||||
layout: LayoutOrientation = .vertical, locale: String = ""
|
||||
) {
|
||||
self.layout = layout
|
||||
maxLinesPerPage = max(1, lines)
|
||||
blankCell = CandidateCellData(key: " ", displayedText: " ", isSelected: false)
|
||||
shitCell = CandidateCellData(key: " ", displayedText: "💩", isSelected: false)
|
||||
blankCell.locale = locale
|
||||
Self.blankCell.locale = locale
|
||||
self.selectionKeys = selectionKeys.isEmpty ? "123456789" : selectionKeys
|
||||
var allCandidates = candidates.map {
|
||||
CandidateCellData(key: " ", displayedText: $0.value, spanLength: $0.keyArray.count)
|
||||
}
|
||||
if allCandidates.isEmpty { allCandidates.append(blankCell) }
|
||||
if allCandidates.isEmpty { allCandidates.append(Self.blankCell) }
|
||||
candidateDataAll = allCandidates
|
||||
candidateLines.removeAll()
|
||||
var currentColumn: [CandidateCellData] = []
|
||||
for (i, candidate) in candidateDataAll.enumerated() {
|
||||
candidate.index = i
|
||||
|
@ -127,7 +145,7 @@ public extension CandidatePool {
|
|||
/// 往指定的方向翻頁。
|
||||
/// - Parameter isBackward: 是否逆向翻頁。
|
||||
/// - Returns: 操作是否順利。
|
||||
@discardableResult mutating func flipPage(isBackward: Bool) -> Bool {
|
||||
@discardableResult func flipPage(isBackward: Bool) -> Bool {
|
||||
backupLineRangeForCurrentPage()
|
||||
defer { flipLineRangeToNeighborPage(isBackward: isBackward) }
|
||||
return consecutivelyFlipLines(isBackward: isBackward, count: maxLinesPerPage)
|
||||
|
@ -147,7 +165,7 @@ public extension CandidatePool {
|
|||
/// - isBackward: 是否逆向翻行。
|
||||
/// - count: 翻幾行。
|
||||
/// - Returns: 操作是否順利。
|
||||
@discardableResult mutating func consecutivelyFlipLines(isBackward: Bool, count: Int) -> Bool {
|
||||
@discardableResult func consecutivelyFlipLines(isBackward: Bool, count: Int) -> Bool {
|
||||
switch isBackward {
|
||||
case false where currentLineNumber == candidateLines.count - 1:
|
||||
return highlightNeighborCandidate(isBackward: false)
|
||||
|
@ -165,7 +183,7 @@ public extension CandidatePool {
|
|||
/// 嘗試高亮前方或者後方的鄰近候選字詞。
|
||||
/// - Parameter isBackward: 是否是後方的鄰近候選字詞。
|
||||
/// - Returns: 是否成功。
|
||||
@discardableResult mutating func highlightNeighborCandidate(isBackward: Bool) -> Bool {
|
||||
@discardableResult func highlightNeighborCandidate(isBackward: Bool) -> Bool {
|
||||
switch isBackward {
|
||||
case false where highlightedIndex >= candidateDataAll.count - 1:
|
||||
highlight(at: 0)
|
||||
|
@ -181,7 +199,7 @@ public extension CandidatePool {
|
|||
|
||||
/// 高亮指定的候選字。
|
||||
/// - Parameter indexSpecified: 給定的候選字詞索引編號,得是資料池內的總索引編號。
|
||||
mutating func highlight(at indexSpecified: Int) {
|
||||
func highlight(at indexSpecified: Int) {
|
||||
var indexSpecified = indexSpecified
|
||||
let isBackward: Bool = indexSpecified > highlightedIndex
|
||||
highlightedIndex = indexSpecified
|
||||
|
@ -222,7 +240,7 @@ public extension CandidatePool {
|
|||
}
|
||||
|
||||
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)
|
||||
var min: CGFloat = defaultMin
|
||||
if layout != .vertical, maxLinesPerPage == 1 {
|
||||
|
@ -267,14 +285,14 @@ private extension CandidatePool {
|
|||
max(0, candidateLines.count - maxLinesPerPage) ..< candidateLines.count
|
||||
}
|
||||
|
||||
mutating func selectNewNeighborLine(isBackward: Bool) {
|
||||
func selectNewNeighborLine(isBackward: Bool) {
|
||||
switch layout {
|
||||
case .horizontal: selectNewNeighborRow(direction: isBackward ? .up : .down)
|
||||
case .vertical: selectNewNeighborColumn(direction: isBackward ? .left : .right)
|
||||
}
|
||||
}
|
||||
|
||||
mutating func fixLineRange(isBackward: Bool = false) {
|
||||
func fixLineRange(isBackward: Bool = false) {
|
||||
if !lineRangeForCurrentPage.contains(currentLineNumber) {
|
||||
switch isBackward {
|
||||
case false:
|
||||
|
@ -289,11 +307,11 @@ private extension CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
mutating func backupLineRangeForCurrentPage() {
|
||||
func backupLineRangeForCurrentPage() {
|
||||
previouslyRecordedLineRangeForPreviousPage = lineRangeForCurrentPage
|
||||
}
|
||||
|
||||
mutating func flipLineRangeToNeighborPage(isBackward: Bool = false) {
|
||||
func flipLineRangeToNeighborPage(isBackward: Bool = false) {
|
||||
guard let prevRange = previouslyRecordedLineRangeForPreviousPage else { return }
|
||||
var lowerBound = prevRange.lowerBound
|
||||
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
|
||||
var result = currentSubIndex
|
||||
branch: switch direction {
|
||||
|
@ -369,7 +387,7 @@ private extension CandidatePool {
|
|||
}
|
||||
}
|
||||
|
||||
mutating func selectNewNeighborColumn(direction: HorizontalDirection) {
|
||||
func selectNewNeighborColumn(direction: HorizontalDirection) {
|
||||
let currentSubIndex = candidateDataAll[highlightedIndex].subIndex
|
||||
switch direction {
|
||||
case .left:
|
||||
|
|
|
@ -25,7 +25,7 @@ extension CandidatePool {
|
|||
private var attributedDescriptionHorizontal: NSAttributedString {
|
||||
let paragraphStyle = sharedParagraphStyle
|
||||
let attrCandidate: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFont(size: blankCell.size),
|
||||
.font: Self.blankCell.phraseFont(size: Self.blankCell.size),
|
||||
.paragraphStyle: paragraphStyle,
|
||||
]
|
||||
let result = NSMutableAttributedString(string: "", attributes: attrCandidate)
|
||||
|
@ -64,7 +64,7 @@ extension CandidatePool {
|
|||
private var attributedDescriptionVertical: NSAttributedString {
|
||||
let paragraphStyle = sharedParagraphStyle
|
||||
let attrCandidate: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFont(size: blankCell.size),
|
||||
.font: Self.blankCell.phraseFont(size: Self.blankCell.size),
|
||||
.paragraphStyle: paragraphStyle,
|
||||
]
|
||||
let result = NSMutableAttributedString(string: "", attributes: attrCandidate)
|
||||
|
@ -129,7 +129,7 @@ extension CandidatePool {
|
|||
let positionCounterColorText = NSColor.controlTextColor
|
||||
let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11)
|
||||
let attrPositionCounter: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFontEmphasized(size: positionCounterTextSize),
|
||||
.font: Self.blankCell.phraseFontEmphasized(size: positionCounterTextSize),
|
||||
.backgroundColor: positionCounterColorBG,
|
||||
.foregroundColor: positionCounterColorText,
|
||||
]
|
||||
|
@ -142,7 +142,7 @@ extension CandidatePool {
|
|||
private var attributedDescriptionTooltip: NSAttributedString {
|
||||
let positionCounterTextSize = max(ceil(CandidateCellData.unifiedSize * 0.7), 11)
|
||||
let attrTooltip: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFontEmphasized(size: positionCounterTextSize),
|
||||
.font: Self.blankCell.phraseFontEmphasized(size: positionCounterTextSize),
|
||||
]
|
||||
let tooltipText = NSAttributedString(
|
||||
string: " \(tooltip) ", attributes: attrTooltip
|
||||
|
@ -153,10 +153,10 @@ extension CandidatePool {
|
|||
private var attributedDescriptionReverseLookp: NSAttributedString {
|
||||
let reverseLookupTextSize = max(ceil(CandidateCellData.unifiedSize * 0.6), 9)
|
||||
let attrReverseLookup: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFont(size: reverseLookupTextSize),
|
||||
.font: Self.blankCell.phraseFont(size: reverseLookupTextSize),
|
||||
]
|
||||
let attrReverseLookupSpacer: [NSAttributedString.Key: AnyObject] = [
|
||||
.font: blankCell.phraseFont(size: reverseLookupTextSize),
|
||||
.font: Self.blankCell.phraseFont(size: reverseLookupTextSize),
|
||||
]
|
||||
let result = NSMutableAttributedString(string: "", attributes: attrReverseLookupSpacer)
|
||||
for neta in reverseLookupResult {
|
||||
|
|
|
@ -31,6 +31,8 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate {
|
|||
public var useMouseScrolling: Bool = true
|
||||
private static var thePool: CandidatePool = .init(candidates: [])
|
||||
private static var currentView: NSView = .init()
|
||||
public static var currentWindow: NSWindow?
|
||||
public static var currentMenu: NSMenu?
|
||||
|
||||
@available(macOS 10.15, *)
|
||||
private var theView: some View {
|
||||
|
|
|
@ -66,9 +66,10 @@ public extension VwrCandidateTDKCocoa {
|
|||
}
|
||||
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
|
||||
thePool.lineRangeForFinalPageBlanked.enumerated().forEach { _ in
|
||||
var theLine = [thePool.blankCell]
|
||||
for _ in 1 ..< thePool.maxLineCapacity {
|
||||
theLine.append(thePool.blankCell)
|
||||
var theLine = [CandidateCellData]()
|
||||
let copied = CandidatePool.blankCell.cleanCopy
|
||||
for _ in 0 ..< thePool.maxLineCapacity {
|
||||
theLine.append(copied)
|
||||
}
|
||||
let vwrCurrentLine = generateLineContainer(&theLine)
|
||||
candidateContainer.addView(vwrCurrentLine, in: isVerticalListing ? .top : .leading)
|
||||
|
@ -88,7 +89,7 @@ public extension VwrCandidateTDKCocoa {
|
|||
let line = Array(lines[viewLineID])
|
||||
columnWidth = line.map(\.visualDimension.width).max() ?? lineDimension.width
|
||||
} else {
|
||||
columnWidth = thePool.blankCell.visualDimension.width
|
||||
columnWidth = CandidatePool.blankCell.visualDimension.width
|
||||
}
|
||||
accumulatedWidth += 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 {
|
||||
let theCell = theCell ?? thePool.blankCell
|
||||
let theCell = theCell ?? CandidatePool.blankCell.cleanCopy
|
||||
let cellLabel = VwrCandidateCell(cell: theCell)
|
||||
cellLabel.target = self
|
||||
Self.makeSimpleConstraint(item: cellLabel, attribute: .width, relation: .equal, value: cellLabel.fittingSize.width)
|
||||
|
@ -362,6 +363,7 @@ private extension VwrCandidateTDKCocoa {
|
|||
}
|
||||
|
||||
theMenu = newMenu
|
||||
CtlCandidateTDK.currentMenu = newMenu
|
||||
}
|
||||
|
||||
@objc func menuActionOfBoosting(_: Any? = nil) {
|
||||
|
|
|
@ -72,9 +72,10 @@ private extension VwrCandidateTDK {
|
|||
.id(rowIndex)
|
||||
}
|
||||
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
|
||||
let copied = CandidatePool.blankCell.cleanCopy
|
||||
ForEach(thePool.lineRangeForFinalPageBlanked, id: \.self) { _ in
|
||||
HStack(spacing: 0) {
|
||||
attributedStringFor(cell: thePool.blankCell)
|
||||
attributedStringFor(cell: copied)
|
||||
.frame(alignment: .topLeading)
|
||||
.contentShape(Rectangle())
|
||||
Spacer()
|
||||
|
@ -102,8 +103,9 @@ private extension VwrCandidateTDK {
|
|||
}
|
||||
.opacity(columnIndex == thePool.currentLineNumber ? 1 : 0.85)
|
||||
if thePool.candidateLines[columnIndex].count < thePool.maxLineCapacity {
|
||||
let copied = CandidatePool.blankCell.cleanCopy
|
||||
ForEach(0 ..< thePool.dummyCellsRequiredForCurrentLine, id: \.self) { _ in
|
||||
drawCandidate(thePool.blankCell)
|
||||
drawCandidate(copied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -112,17 +114,15 @@ private extension VwrCandidateTDK {
|
|||
alignment: .topLeading
|
||||
)
|
||||
.id(columnIndex)
|
||||
if thePool.maxLinesPerPage > 1, thePool.maxLinesPerPage <= loopIndex + 1 {
|
||||
Spacer(minLength: 0)
|
||||
}
|
||||
}
|
||||
if thePool.maxLinesPerPage - thePool.lineRangeForCurrentPage.count > 0 {
|
||||
ForEach(Array(thePool.lineRangeForFinalPageBlanked.enumerated()), id: \.offset) { loopIndex, _ in
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
let copied = CandidatePool.blankCell.cleanCopy
|
||||
ForEach(0 ..< thePool.maxLineCapacity, id: \.self) { _ in
|
||||
attributedStringFor(cell: thePool.blankCell).fixedSize()
|
||||
attributedStringFor(cell: copied).fixedSize()
|
||||
.frame(
|
||||
width: ceil(thePool.blankCell.cellLength(isMatrix: true)),
|
||||
width: ceil(CandidatePool.blankCell.cellLength(isMatrix: true)),
|
||||
alignment: .topLeading
|
||||
)
|
||||
.contentShape(Rectangle())
|
||||
|
@ -132,11 +132,6 @@ private extension VwrCandidateTDK {
|
|||
maxWidth: .infinity,
|
||||
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 maxWindowWith: CGFloat
|
||||
= ceil(
|
||||
Double(thePool.maxLineCapacity) * (thePool.blankCell.cellLength())
|
||||
Double(thePool.maxLineCapacity) * (CandidatePool.blankCell.cellLength())
|
||||
+ spacings
|
||||
)
|
||||
return thePool.layout == .horizontal && thePool.maxLinesPerPage > 1 ? maxWindowWith : nil
|
||||
|
@ -245,7 +240,7 @@ extension VwrCandidateTDK {
|
|||
HStack {
|
||||
if !tooltip.isEmpty {
|
||||
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))
|
||||
}.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 tooltip = "📼"
|
||||
@State static var oldOS: Bool = true
|
||||
@State static var oldOS: Bool = false
|
||||
|
||||
static var testCandidatesConverted: [(keyArray: [String], value: String)] {
|
||||
testCandidates.map { candidate in
|
||||
|
@ -381,7 +376,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
|
|||
}
|
||||
|
||||
static var thePoolX: CandidatePool {
|
||||
var result = CandidatePool(
|
||||
let result = CandidatePool(
|
||||
candidates: testCandidatesConverted, lines: 4,
|
||||
selectionKeys: "123456", layout: .horizontal
|
||||
)
|
||||
|
@ -392,7 +387,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
|
|||
}
|
||||
|
||||
static var thePoolXS: CandidatePool {
|
||||
var result = CandidatePool(
|
||||
let result = CandidatePool(
|
||||
candidates: testCandidatesConverted, lines: 1,
|
||||
selectionKeys: "123456", layout: .horizontal
|
||||
)
|
||||
|
@ -403,7 +398,7 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
|
|||
}
|
||||
|
||||
static var thePoolY: CandidatePool {
|
||||
var result = CandidatePool(
|
||||
let result = CandidatePool(
|
||||
candidates: testCandidatesConverted, lines: 4,
|
||||
selectionKeys: "123456", layout: .vertical
|
||||
)
|
||||
|
@ -411,11 +406,12 @@ struct VwrCandidateTDK_Previews: PreviewProvider {
|
|||
result.tooltip = Self.tooltip
|
||||
result.flipPage(isBackward: false)
|
||||
result.highlight(at: 2)
|
||||
result.highlight(at: 21)
|
||||
return result
|
||||
}
|
||||
|
||||
static var thePoolYS: CandidatePool {
|
||||
var result = CandidatePool(
|
||||
let result = CandidatePool(
|
||||
candidates: testCandidatesConverted, lines: 1,
|
||||
selectionKeys: "123456", layout: .vertical
|
||||
)
|
||||
|
|
|
@ -273,6 +273,14 @@ public extension SessionCtl {
|
|||
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
|
||||
if isActivated { return }
|
||||
|
||||
|
|
Loading…
Reference in New Issue