From 625897a744a0b433b4d4d448c4737614fd61dcb9 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 9 Mar 2023 16:32:48 +0800 Subject: [PATCH] Repo // Call candidatePairHighlightChanged() when appropriate. --- .../TDKCandidates/CtlCandidateTDK.swift | 1 + .../SessionCtl_IMKCandidatesData.swift | 105 ++++++++++-------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift index c8453d3a..77d6b686 100644 --- a/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift +++ b/Packages/vChewing_CandidateWindow/Sources/CandidateWindow/TDKCandidates/CtlCandidateTDK.swift @@ -88,6 +88,7 @@ public class CtlCandidateTDK: CtlCandidate, NSWindowDelegate { reverseLookupResult = delegate?.reverseLookup(for: currentCandidateText) ?? [] Self.thePool.reverseLookupResult = reverseLookupResult } + delegate?.candidatePairHighlightChanged(at: highlightedIndex) DispatchQueue.main.async { [self] in window.isOpaque = false window.backgroundColor = .clear diff --git a/Source/Modules/SessionCtl_IMKCandidatesData.swift b/Source/Modules/SessionCtl_IMKCandidatesData.swift index 69abe2b5..39250fd6 100644 --- a/Source/Modules/SessionCtl_IMKCandidatesData.swift +++ b/Source/Modules/SessionCtl_IMKCandidatesData.swift @@ -69,14 +69,20 @@ public extension SessionCtl { /// IMK 選字窗限定函式,只要選字窗內的高亮內容選擇出現變化了、就會呼叫這個函式。 /// - Parameter currentSelection: 已經高亮選中的候選字詞內容。 override func candidateSelectionChanged(_ currentSelection: NSAttributedString!) { - guard let currentCandidate = currentSelection?.string, !currentCandidate.isEmpty else { return } - let annotation = reverseLookup(for: currentCandidate).joined(separator: "\n") - guard !annotation.isEmpty else { return } - vCLog("Current Annotation: \(annotation)") + guard let candidateString = currentSelection?.string, !candidateString.isEmpty else { return } + // Handle IMK Annotation... We just use this to tell Apple that this never works in IMKCandidates. DispatchQueue.main.async { [self] in + let annotation = reverseLookup(for: candidateString).joined(separator: "\n") + guard !annotation.isEmpty else { return } + vCLog("Current Annotation: \(annotation)") guard let imkCandidates = candidateUI as? CtlCandidateIMK else { return } imkCandidates.showAnnotation(.init(string: annotation)) } + // Handle candidatePairHighlightChanged(). + guard state.type == .ofCandidates else { return } + var indexDeducted = 0 + fixIndexForIMKCandidates(&indexDeducted, source: candidateString) + candidatePairHighlightChanged(at: indexDeducted) } /// IMK 選字窗限定函式,只要選字窗確認了某個候選字詞的選擇、就會呼叫這個函式。 @@ -85,6 +91,7 @@ public extension SessionCtl { override func candidateSelected(_ candidateString: NSAttributedString!) { let candidateString: String = candidateString?.string ?? "" if state.type == .ofAssociates { + // 聯想詞的 Shift+選字鍵的處理已經在其它位置實作完成。 if !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter { switchState(IMEState.ofAbortion()) return @@ -93,45 +100,9 @@ public extension SessionCtl { var indexDeducted = 0 - // 注意:下文中的不可列印字元是用來方便在 IMEState 當中用來分割資料的。 - func handleIMKCandidatesSelected( - _ candidates: [(keyArray: [String], value: String)], prefix: String = "" - ) { - guard let separator = inputHandler?.keySeparator else { return } - for (i, neta) in candidates.enumerated() { - let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.value) - let netaShown = (neta.value == theConverted) - ? neta.value - : "\(theConverted)\u{1A}(\(neta.value))" - let reading: String = - PrefMgr.shared.cassetteEnabled - ? neta.keyArray.joined(separator: separator) - : (PrefMgr.shared.showHanyuPinyinInCompositionBuffer - ? Tekkon.cnvPhonaToHanyuPinyin( - targetJoined: { - var arr = [String]() - neta.keyArray.forEach { key in - arr.append(Tekkon.restoreToneOneInPhona(target: key)) - } - return arr.joined(separator: "-") - }() - ) - : neta.keyArray.joined(separator: separator)) - let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))" - if candidateString == prefix + netaShownWithPronunciation { - indexDeducted = i - break - } - if candidateString == prefix + netaShown { - indexDeducted = i - break - } - } - } - // 分類符號選單不會出現同符異音項、不需要康熙 / JIS 轉換,所以使用簡化過的處理方式。 - func handleSymbolCandidatesSelected(_ candidates: [(keyArray: [String], value: String)]) { - for (i, neta) in candidates.enumerated() { + func fixSymbolIndexForIMKCandidates() { + for (i, neta) in state.candidates.enumerated() { if candidateString == neta.value { indexDeducted = i break @@ -140,17 +111,59 @@ public extension SessionCtl { } if state.type == .ofAssociates { - handleIMKCandidatesSelected(state.candidates, prefix: "⇧") + fixIndexForIMKCandidates(&indexDeducted, prefix: "⇧", source: candidateString) } else if state.type == .ofSymbolTable { - handleSymbolCandidatesSelected(state.candidates) + fixSymbolIndexForIMKCandidates() } else if state.type == .ofCandidates { guard !state.candidates.isEmpty else { return } if state.candidates[0].keyArray.description.contains("_punctuation") { - handleSymbolCandidatesSelected(state.candidates) // 標點符號選單處理。 + fixSymbolIndexForIMKCandidates() // 標點符號選單處理。 } else { - handleIMKCandidatesSelected(state.candidates) + fixIndexForIMKCandidates(&indexDeducted, source: candidateString) } } candidatePairSelectionConfirmed(at: indexDeducted) } + + /// 解析 IMKCandidates 給出的資料參數,據此推算正確的被確認的候選字詞配對的編號。 + /// - Remark: 該函式當中的不可列印字元`\u{1A`是用來方便在 IMEState 當中用來分割資料的。 + /// - Parameters: + /// - prefix: 前綴(僅限於聯想詞模式)。 + /// - indexToFix: 要糾正的編號變數。 + /// - candidateString: IMKCandidates 給出的原始資料。 + private func fixIndexForIMKCandidates( + _ indexDeducted: inout Int, prefix: String = "", source candidateString: String + ) { + guard let separator = inputHandler?.keySeparator else { return } + let candidates = state.candidates + for (i, neta) in candidates.enumerated() { + let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.value) + let netaShown = (neta.value == theConverted) + ? neta.value + : "\(theConverted)\u{1A}(\(neta.value))" + let reading: String = + PrefMgr.shared.cassetteEnabled + ? neta.keyArray.joined(separator: separator) + : (PrefMgr.shared.showHanyuPinyinInCompositionBuffer + ? Tekkon.cnvPhonaToHanyuPinyin( + targetJoined: { + var arr = [String]() + neta.keyArray.forEach { key in + arr.append(Tekkon.restoreToneOneInPhona(target: key)) + } + return arr.joined(separator: "-") + }() + ) + : neta.keyArray.joined(separator: separator)) + let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))" + if candidateString == prefix + netaShownWithPronunciation { + indexDeducted = i + break + } + if candidateString == prefix + netaShown { + indexDeducted = i + break + } + } + } }