IMKCandidates // Reorganization.

This commit is contained in:
ShikiSuen 2022-09-24 12:20:14 +08:00
parent 0ce0604c16
commit 690df020bd
4 changed files with 286 additions and 263 deletions

View File

@ -9,11 +9,9 @@
// requirements defined in MIT License.
import IMKUtils
import NotifierUI
import PopupCompositionBuffer
import Shared
import ShiftKeyUpChecker
import Tekkon
import TooltipUI
///
@ -78,8 +76,46 @@ class ctlInputMethod: IMKInputController {
return result
}
// MARK: -
/// InputMode
/// IME UserPrefs
var inputMode: Shared.InputMode = IMEApp.currentInputMode {
willSet {
/// Prefs IME
IMEApp.currentInputMode = newValue
PrefMgr.shared.mostRecentInputMode = IMEApp.currentInputMode.rawValue
}
didSet {
///
keyHandler.currentLM = LMMgr.currentLM() //
keyHandler.currentUOM = LMMgr.currentUOM()
///
keyHandler.ensureKeyboardParser()
///
syncBaseLMPrefs()
}
}
///
///
/// inputClient IMKServer IMKTextInput
/// - Remark: IMKInputController client()
/// - Parameters:
/// - server: IMKServer
/// - delegate:
/// - inputClient:
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
super.init(server: server, delegate: delegate, client: inputClient)
keyHandler.delegate = self
syncBaseLMPrefs()
//
resetKeyHandler()
activateServer(inputClient)
}
}
// MARK: -
extension ctlInputMethod {
///
func setKeyLayout() {
guard let client = client() else { return }
@ -104,28 +140,11 @@ class ctlInputMethod: IMKInputController {
}
handle(state: isSecureMode ? IMEState.ofAbortion() : IMEState.ofEmpty())
}
}
// MARK: - IMKInputController
///
///
/// inputClient IMKServer IMKTextInput
/// - Remark: IMKInputController client()
/// - Parameters:
/// - server: IMKServer
/// - delegate:
/// - inputClient:
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
super.init(server: server, delegate: delegate, client: inputClient)
keyHandler.delegate = self
syncBaseLMPrefs()
//
resetKeyHandler()
activateServer(inputClient)
}
// MARK: - IMKStateSetting
// MARK: - IMKStateSetting
extension ctlInputMethod {
///
/// - Parameter sender: 使
override func activateServer(_ sender: Any!) {
@ -195,25 +214,6 @@ class ctlInputMethod: IMKInputController {
}
}
/// InputMode
/// IME UserPrefs
var inputMode: Shared.InputMode = IMEApp.currentInputMode {
willSet {
/// Prefs IME
IMEApp.currentInputMode = newValue
PrefMgr.shared.mostRecentInputMode = IMEApp.currentInputMode.rawValue
}
didSet {
///
keyHandler.currentLM = LMMgr.currentLM() //
keyHandler.currentUOM = LMMgr.currentUOM()
///
keyHandler.ensureKeyboardParser()
///
syncBaseLMPrefs()
}
}
///
func syncBaseLMPrefs() {
LMMgr.currentLM().isPhraseReplacementEnabled = PrefMgr.shared.phraseReplacementEnabled
@ -222,9 +222,13 @@ class ctlInputMethod: IMKInputController {
LMMgr.currentLM().isSCPCEnabled = PrefMgr.shared.useSCPCTypingMode
LMMgr.currentLM().deltaOfCalendarYears = PrefMgr.shared.deltaOfCalendarYears
}
}
// MARK: - IMKServerInput
// MARK: - IMKServerInput
// handle(_ event:) ctlInputMethod_HandleEvent.swift
extension ctlInputMethod {
///
///
///
@ -240,104 +244,6 @@ class ctlInputMethod: IMKInputController {
return Int(events.rawValue)
}
/// NSEvent
/// - Parameters:
/// - event: nil
/// - sender: 使
/// - Returns: `true` IMK`false`
@objc(handleEvent:client:) override func handle(_ event: NSEvent!, client sender: Any!) -> Bool {
_ = sender //
// MARK:
//
state.isASCIIMode = isASCIIMode
state.isVerticalTyping = isVerticalTyping
// NSEvent nilApple InputMethodKit
// client()
guard let event = event, sender is IMKTextInput else {
resetKeyHandler()
return false
}
// Shift macOS 10.15 macOS
let shouldUseShiftToggleHandle: Bool = {
switch PrefMgr.shared.shiftKeyAccommodationBehavior {
case 0: return false
case 1: return Shared.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
case 2: return true
default: return false
}
}()
/// event event var Shift
if #available(macOS 10.15, *) {
if Self.theShiftKeyDetector.check(event), !PrefMgr.shared.disableShiftTogglingAlphanumericalMode {
if !shouldUseShiftToggleHandle || (!rencentKeyHandledByKeyHandlerEtc && shouldUseShiftToggleHandle) {
let status = NSLocalizedString("NotificationSwitchShift", comment: "")
Notifier.notify(
message: isASCIIMode.toggled()
? NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status
: NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status
)
}
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = false
}
return false
}
}
// MARK:
// Shift
if isASCIIMode { return false }
/// flags使 KeyHandler
/// flags
/// event.type == .flagsChanged return false
/// NSInternalInconsistencyException
if event.type == .flagsChanged { return false }
///
guard client() != nil else { return false }
var eventToDeal = event
//
if event.isUp || event.isDown || event.isLeft || event.isRight {
eventToDeal = event.reinitiate(charactersIgnoringModifiers: isVerticalTyping ? "Vertical" : "Horizontal") ?? event
}
// 使 NSEvent Emacs NSEvent NSEvent
if eventToDeal.isEmacsKey {
let verticalProcessing =
(state.isCandidateContainer)
? state.isVerticalCandidateWindow : state.isVerticalTyping
eventToDeal = eventToDeal.convertFromEmacKeyEvent(isVerticalContext: verticalProcessing)
}
//
Self.areWeNerfing = eventToDeal.modifierFlags.contains([.shift, .command])
// IMK IMK
if let result = imkCandidatesEventPreHandler(event: eventToDeal) {
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = result
}
return result
}
/// NSEvent commonEventHandler
/// IMK 便
let result = commonEventHandler(eventToDeal)
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = result
}
return result
}
/// App Ctrl+Enter / Shift+Enter
/// handle(event:) Event
/// commitComposition
@ -348,13 +254,13 @@ class ctlInputMethod: IMKInputController {
// super.commitComposition(sender) //
}
///
/// InputMethodKit
/// - Parameter sender: 使
/// - Returns: nil
override func composedString(_ sender: Any!) -> Any! {
_ = sender //
guard state.hasComposition else { return "" }
return state.displayedText
return state.displayedTextConverted
}
///
@ -364,121 +270,4 @@ class ctlInputMethod: IMKInputController {
resetKeyHandler()
super.inputControllerWillClose()
}
// MARK: - IMKCandidates
/// IMK
/// - Parameter sender: 使
/// - Returns: IMK
override func candidates(_ sender: Any!) -> [Any]! {
_ = sender //
var arrResult = [String]()
// 便 IMEState
func handleIMKCandidatesPrepared(_ candidates: [(String, String)], prefix: String = "") {
for theCandidate in candidates {
let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.1)
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)\u{1A}(\(theCandidate.1))"
if arrResult.contains(result) {
let reading: String =
PrefMgr.shared.showHanyuPinyinInCompositionBuffer
? Tekkon.cnvPhonaToHanyuPinyin(target: Tekkon.restoreToneOneInZhuyinKey(target: theCandidate.0))
: theCandidate.0
result = "\(result)\u{17}(\(reading))"
}
arrResult.append(prefix + result)
}
}
if state.type == .ofAssociates {
handleIMKCandidatesPrepared(state.candidates, prefix: "")
} else if state.type == .ofSymbolTable {
// / JIS 使
arrResult = state.candidates.map(\.1)
} else if state.type == .ofCandidates {
guard !state.candidates.isEmpty else { return .init() }
if state.candidates[0].0.contains("_punctuation") {
arrResult = state.candidates.map(\.1) //
} else {
handleIMKCandidatesPrepared(state.candidates)
}
}
return arrResult
}
/// IMK
/// - Parameter _:
override open func candidateSelectionChanged(_: NSAttributedString!) {
//
// IMKServer.commitCompositionWithReply() commitComposition()
// keyHandler
//
//
// ctlCandidateIMK identifier
// NSNotFound NSLog identifier
// console ips
// candidateSelected() identifier NSNotFound
// IMK 西
}
/// IMK
/// - Parameter candidateString:
override open func candidateSelected(_ candidateString: NSAttributedString!) {
let candidateString: String = candidateString?.string ?? ""
if state.type == .ofAssociates {
if !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter {
handle(state: IMEState.ofAbortion())
return
}
}
var indexDeducted = 0
// 便 IMEState
func handleIMKCandidatesSelected(_ candidates: [(String, String)], prefix: String = "") {
for (i, neta) in candidates.enumerated() {
let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.1)
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)\u{1A}(\(neta.1))"
let reading: String =
PrefMgr.shared.showHanyuPinyinInCompositionBuffer
? Tekkon.cnvPhonaToHanyuPinyin(target: Tekkon.restoreToneOneInZhuyinKey(target: neta.0)) : neta.0
let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))"
if candidateString == prefix + netaShownWithPronunciation {
indexDeducted = i
break
}
if candidateString == prefix + netaShown {
indexDeducted = i
break
}
}
}
// / JIS 使
func handleSymbolCandidatesSelected(_ candidates: [(String, String)]) {
for (i, neta) in candidates.enumerated() {
if candidateString == neta.1 {
indexDeducted = i
break
}
}
}
if state.type == .ofAssociates {
handleIMKCandidatesSelected(state.candidates, prefix: "")
} else if state.type == .ofSymbolTable {
handleSymbolCandidatesSelected(state.candidates)
} else if state.type == .ofCandidates {
guard !state.candidates.isEmpty else { return }
if state.candidates[0].0.contains("_punctuation") {
handleSymbolCandidatesSelected(state.candidates) //
} else {
handleIMKCandidatesSelected(state.candidates)
}
}
candidateSelected(at: indexDeducted)
}
}

View File

@ -9,14 +9,115 @@
// requirements defined in MIT License.
import InputMethodKit
import NotifierUI
import Shared
// MARK: - Facade
extension ctlInputMethod {
/// NSEvent
/// - Parameters:
/// - event: nil
/// - sender: 使
/// - Returns: `true` IMK`false`
@objc(handleEvent:client:) override func handle(_ event: NSEvent!, client sender: Any!) -> Bool {
_ = sender //
// MARK:
//
state.isASCIIMode = isASCIIMode
state.isVerticalTyping = isVerticalTyping
// NSEvent nilApple InputMethodKit
// client()
guard let event = event, sender is IMKTextInput else {
resetKeyHandler()
return false
}
// Shift macOS 10.15 macOS
let shouldUseShiftToggleHandle: Bool = {
switch PrefMgr.shared.shiftKeyAccommodationBehavior {
case 0: return false
case 1: return Shared.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
case 2: return true
default: return false
}
}()
/// event event var Shift
if #available(macOS 10.15, *) {
if Self.theShiftKeyDetector.check(event), !PrefMgr.shared.disableShiftTogglingAlphanumericalMode {
if !shouldUseShiftToggleHandle || (!rencentKeyHandledByKeyHandlerEtc && shouldUseShiftToggleHandle) {
let status = NSLocalizedString("NotificationSwitchShift", comment: "")
Notifier.notify(
message: isASCIIMode.toggled()
? NSLocalizedString("Alphanumerical Input Mode", comment: "") + "\n" + status
: NSLocalizedString("Chinese Input Mode", comment: "") + "\n" + status
)
}
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = false
}
return false
}
}
// MARK:
// Shift
if isASCIIMode { return false }
/// flags使 KeyHandler
/// flags
/// event.type == .flagsChanged return false
/// NSInternalInconsistencyException
if event.type == .flagsChanged { return false }
///
guard client() != nil else { return false }
var eventToDeal = event
//
if event.isUp || event.isDown || event.isLeft || event.isRight {
eventToDeal = event.reinitiate(charactersIgnoringModifiers: isVerticalTyping ? "Vertical" : "Horizontal") ?? event
}
// 使 NSEvent Emacs NSEvent NSEvent
if eventToDeal.isEmacsKey {
let verticalProcessing = (state.isCandidateContainer) ? state.isVerticalCandidateWindow : state.isVerticalTyping
eventToDeal = eventToDeal.convertFromEmacKeyEvent(isVerticalContext: verticalProcessing)
}
//
Self.areWeNerfing = eventToDeal.modifierFlags.contains([.shift, .command])
// IMK IMK
if let result = imkCandidatesEventPreHandler(event: eventToDeal) {
if shouldUseShiftToggleHandle { rencentKeyHandledByKeyHandlerEtc = result }
return result
}
/// NSEvent commonEventHandler
/// IMK 便
let result = commonEventHandler(eventToDeal)
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = result
}
return result
}
}
// MARK: - Private functions
extension ctlInputMethod {
/// handle() IMK
/// handle()
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
func commonEventHandler(_ event: NSEvent) -> Bool {
private func commonEventHandler(_ event: NSEvent) -> Bool {
//
// KeyHandler
if !event.charCode.isPrintable { return false }
@ -37,7 +138,7 @@ extension ctlInputMethod {
/// handle()
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
func imkCandidatesEventPreHandler(event eventToDeal: NSEvent) -> Bool? {
private func imkCandidatesEventPreHandler(event eventToDeal: NSEvent) -> Bool? {
// IMK IMK
// interpretKeyEvents()
// - imkCandidates.interpretKeyEvents()
@ -74,7 +175,7 @@ extension ctlInputMethod {
return nil
}
func imkCandidatesEventSubHandler(event: NSEvent) -> Bool {
private func imkCandidatesEventSubHandler(event: NSEvent) -> Bool {
let eventArray = [event]
guard let imkC = Self.ctlCandidateCurrent as? ctlCandidateIMK else { return false }
if event.isEsc || event.isBackSpace || event.isDelete || (event.isShiftHold && !event.isSpace) {

View File

@ -0,0 +1,129 @@
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import Foundation
import Tekkon
// MARK: - IMKCandidates
extension ctlInputMethod {
/// IMK
/// - Parameter sender: 使
/// - Returns: IMK
override func candidates(_ sender: Any!) -> [Any]! {
_ = sender //
var arrResult = [String]()
// 便 IMEState
func handleIMKCandidatesPrepared(_ candidates: [(String, String)], prefix: String = "") {
for theCandidate in candidates {
let theConverted = ChineseConverter.kanjiConversionIfRequired(theCandidate.1)
var result = (theCandidate.1 == theConverted) ? theCandidate.1 : "\(theConverted)\u{1A}(\(theCandidate.1))"
if arrResult.contains(result) {
let reading: String =
PrefMgr.shared.showHanyuPinyinInCompositionBuffer
? Tekkon.cnvPhonaToHanyuPinyin(target: Tekkon.restoreToneOneInZhuyinKey(target: theCandidate.0))
: theCandidate.0
result = "\(result)\u{17}(\(reading))"
}
arrResult.append(prefix + result)
}
}
if state.type == .ofAssociates {
handleIMKCandidatesPrepared(state.candidates, prefix: "")
} else if state.type == .ofSymbolTable {
// / JIS 使
arrResult = state.candidates.map(\.1)
} else if state.type == .ofCandidates {
guard !state.candidates.isEmpty else { return .init() }
if state.candidates[0].0.contains("_punctuation") {
arrResult = state.candidates.map(\.1) //
} else {
handleIMKCandidatesPrepared(state.candidates)
}
}
return arrResult
}
/// IMK
/// - Parameter _:
override open func candidateSelectionChanged(_: NSAttributedString!) {
//
// IMKServer.commitCompositionWithReply() commitComposition()
// keyHandler
//
//
// ctlCandidateIMK identifier
// NSNotFound NSLog identifier
// console ips
// candidateSelected() identifier NSNotFound
// IMK 西
}
/// IMK
/// - Parameter candidateString:
override open func candidateSelected(_ candidateString: NSAttributedString!) {
let candidateString: String = candidateString?.string ?? ""
if state.type == .ofAssociates {
if !PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter {
handle(state: IMEState.ofAbortion())
return
}
}
var indexDeducted = 0
// 便 IMEState
func handleIMKCandidatesSelected(_ candidates: [(String, String)], prefix: String = "") {
for (i, neta) in candidates.enumerated() {
let theConverted = ChineseConverter.kanjiConversionIfRequired(neta.1)
let netaShown = (neta.1 == theConverted) ? neta.1 : "\(theConverted)\u{1A}(\(neta.1))"
let reading: String =
PrefMgr.shared.showHanyuPinyinInCompositionBuffer
? Tekkon.cnvPhonaToHanyuPinyin(target: Tekkon.restoreToneOneInZhuyinKey(target: neta.0)) : neta.0
let netaShownWithPronunciation = "\(netaShown)\u{17}(\(reading))"
if candidateString == prefix + netaShownWithPronunciation {
indexDeducted = i
break
}
if candidateString == prefix + netaShown {
indexDeducted = i
break
}
}
}
// / JIS 使
func handleSymbolCandidatesSelected(_ candidates: [(String, String)]) {
for (i, neta) in candidates.enumerated() {
if candidateString == neta.1 {
indexDeducted = i
break
}
}
}
if state.type == .ofAssociates {
handleIMKCandidatesSelected(state.candidates, prefix: "")
} else if state.type == .ofSymbolTable {
handleSymbolCandidatesSelected(state.candidates)
} else if state.type == .ofCandidates {
guard !state.candidates.isEmpty else { return }
if state.candidates[0].0.contains("_punctuation") {
handleSymbolCandidatesSelected(state.candidates) //
} else {
handleIMKCandidatesSelected(state.candidates)
}
}
candidateSelected(at: indexDeducted)
}
}

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
5B00FA0C28DEC17200F6D436 /* ctlInputMethod_IMKCandidatesData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B00FA0B28DEC17200F6D436 /* ctlInputMethod_IMKCandidatesData.swift */; };
5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; };
5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; };
5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */; };
@ -154,6 +155,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
5B00FA0B28DEC17200F6D436 /* ctlInputMethod_IMKCandidatesData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_IMKCandidatesData.swift; sourceTree = "<group>"; };
5B04305327B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
5B04305427B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
5B04305527B529D800CB65BC /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = "<group>"; };
@ -663,6 +665,7 @@
5B21176D28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift */,
5B6C141128A9D4B30098ADF8 /* ctlInputMethod_HandleEvent.swift */,
5B21176B287539BB000443A9 /* ctlInputMethod_HandleStates.swift */,
5B00FA0B28DEC17200F6D436 /* ctlInputMethod_IMKCandidatesData.swift */,
5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */,
5BF56F9728C39A2700DD6839 /* IMEState.swift */,
5BF56F9928C39D1800DD6839 /* IMEStateData.swift */,
@ -1073,6 +1076,7 @@
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */,
5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */,
5BE377A0288FED8D0037365B /* KeyHandler_HandleComposition.swift in Sources */,
5B00FA0C28DEC17200F6D436 /* ctlInputMethod_IMKCandidatesData.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};