SessionCtl // Refactor the menu structure.

This commit is contained in:
ShikiSuen 2024-02-08 22:51:18 +08:00
parent a219b7881f
commit bb9bc058cc
3 changed files with 344 additions and 449 deletions

View File

@ -0,0 +1,344 @@
// (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 AppKit
import CocoaExtension
import NotifierUI
import Shared
import SwiftExtension
// MARK: - IME Menu Manager
//
extension SessionCtl {
var optionKeyPressed: Bool { NSEvent.keyModifierFlags.contains(.option) }
var silentMode: Bool { clientBundleIdentifier == "com.apple.SecurityAgent" }
var currentRAMUsageDescription: String? {
guard PrefMgr.shared.isDebugModeEnabled else { return nil }
guard let currentMemorySizeInBytes = NSApplication.memoryFootprint else { return nil }
let currentMemorySize: Double = (Double(currentMemorySizeInBytes) / 1024 / 1024).rounded(toPlaces: 1)
return "Total RAM Usage: \(currentMemorySize)MB"
}
override public func menu() -> NSMenu {
.init().appendItems(self) {
NSMenu.Item(verbatim: currentRAMUsageDescription)
NSMenu.Item(
verbatim: String(
format: "Switch to %@ Input Mode".localized,
IMEApp.currentInputMode.reversed.localizedDescription
)
)?.act(#selector(switchInputMode(_:)))
.hotkey(PrefMgr.shared.usingHotKeyInputMode ? "D" : "", mask: [.command, .control])
NSMenu.Item("Per-Char Select Mode")?
.act(#selector(toggleSCPCTypingMode(_:)))
.state(PrefMgr.shared.useSCPCTypingMode)
.hotkey(PrefMgr.shared.usingHotKeySCPC ? "P" : "", mask: [.command, .control])
NSMenu.Item("Associated Phrases")?
.act(#selector(toggleAssociatedPhrasesEnabled(_:)))
.state(PrefMgr.shared.associatedPhrasesEnabled)
.hotkey(PrefMgr.shared.usingHotKeyAssociates ? "O" : "", mask: [.command, .control])
NSMenu.Item("CIN Cassette Mode")?
.act(#selector(toggleCassetteMode(_:)))
.state(PrefMgr.shared.cassetteEnabled)
.hotkey(PrefMgr.shared.usingHotKeyCassette ? "I" : "", mask: [.command, .control])
NSMenu.Item("CNS11643 Mode")?
.act(#selector(toggleCNS11643Enabled(_:)))
.state(PrefMgr.shared.cns11643Enabled)
.hotkey(PrefMgr.shared.usingHotKeyCNS ? "L" : "", mask: [.command, .control])
NSMenu.Item("Force KangXi Writing")?
.act(#selector(toggleChineseConverter(_:)))
.state(PrefMgr.shared.chineseConversionEnabled)
.hotkey(PrefMgr.shared.usingHotKeyKangXi ? "K" : "", mask: [.command, .control])
.nulled(IMEApp.currentInputMode != .imeModeCHT)
NSMenu.Item("JIS Shinjitai Output")?
.act(#selector(toggleShiftJISShinjitaiOutput(_:)))
.state(PrefMgr.shared.shiftJISShinjitaiOutputEnabled)
.hotkey(PrefMgr.shared.usingHotKeyJIS ? "J" : "", mask: [.command, .control])
.nulled(IMEApp.currentInputMode != .imeModeCHT)
NSMenu.Item("Currency Numeral Output")?
.act(#selector(toggleCurrencyNumerals(_:)))
.state(PrefMgr.shared.currencyNumeralsEnabled)
.hotkey(PrefMgr.shared.usingHotKeyCurrencyNumerals ? "M" : "", mask: [.command, .control])
NSMenu.Item("Half-Width Punctuation Mode")?
.act(#selector(toggleHalfWidthPunctuation(_:)))
.state(PrefMgr.shared.halfWidthPunctuationEnabled)
.hotkey(PrefMgr.shared.usingHotKeyHalfWidthASCII ? "H" : "", mask: [.command, .control])
NSMenu.Item("Use Phrase Replacement")?
.act(#selector(togglePhraseReplacement(_:)))
.state(PrefMgr.shared.phraseReplacementEnabled)
.nulled(!optionKeyPressed && !PrefMgr.shared.phraseReplacementEnabled)
NSMenu.Item("Symbol & Emoji Input")?
.act(#selector(toggleSymbolEnabled(_:)))
.state(PrefMgr.shared.symbolInputEnabled)
.nulled(!optionKeyPressed)
NSMenu.Item.separator() // ---------------------
NSMenu.Item("Open User Dictionary Folder")?.act(#selector(openUserDataFolder(_:))).nulled(silentMode)
NSMenu.Item("Edit vChewing User Phrases…")?.act(#selector(openUserPhrases(_:))).nulled(silentMode)
NSMenu.Item("Edit Excluded Phrases…")?.act(#selector(openExcludedPhrases(_:))).nulled(silentMode)
NSMenu.Item("Edit Associated Phrases…")?.act(#selector(openAssociatedPhrases(_:))).nulled(
!(!silentMode && (optionKeyPressed || PrefMgr.shared.associatedPhrasesEnabled))
)
NSMenu.Item("Edit Phrase Replacement Table…")?.act(#selector(openPhraseReplacement(_:))).nulled(silentMode || !optionKeyPressed)
NSMenu.Item("Edit User Symbol & Emoji Data…")?.act(#selector(openUserSymbols(_:))).nulled(silentMode || !optionKeyPressed)
NSMenu.Item("Open App Support Folder")?.act(#selector(openAppSupportFolderFromContainer(_:))).nulled(silentMode || !optionKeyPressed)
NSMenu.Item("Reload User Phrases")?.act(#selector(reloadUserPhrasesData(_:))).nulled(PrefMgr.shared.shouldAutoReloadUserDataFiles && !optionKeyPressed)
NSMenu.Item(verbatim: "Reverse Lookup (Phonabets)".localized.withEllipsis)?
.act(#selector(callReverseLookupWindow(_:))).hotkey(PrefMgr.shared.usingHotKeyRevLookup ? "/" : "", mask: [.command, .control])
NSMenu.Item("Optimize Memorized Phrases")?.act(#selector(removeUnigramsFromUOM(_:)))
NSMenu.Item("Clear Memorized Phrases")?.act(#selector(clearUOM(_:)))
NSMenu.Item.separator() // ---------------------
if #unavailable(macOS 13) {
NSMenu.Item("vChewing Preferences…")?.act(#selector(showPreferences(_:))).nulled(silentMode)
} else {
NSMenu.Item(
verbatim: "vChewing Preferences…".localized + " (SwiftUI)"
)?.act(#selector(showSettingsSwiftUI(_:))).nulled(silentMode)
NSMenu.Item(
verbatim: "vChewing Preferences…".localized + " (AppKit)"
)?.act(#selector(showSettingsAppKit(_:))).nulled(silentMode)
}
NSMenu.Item(verbatim: "Client Manager".localized.withEllipsis)?.act(#selector(showClientListMgr(_:))).nulled(silentMode)
NSMenu.Item("Check for Updates…")?.act(#selector(checkForUpdate(_:))).nulled(silentMode)
NSMenu.Item("Reboot vChewing…")?.act(#selector(selfTerminate(_:)))
NSMenu.Item("About vChewing…")?.act(#selector(showAbout(_:))).nulled(silentMode)
NSMenu.Item("CheatSheet")?.act(#selector(showCheatSheet(_:))).nulled(silentMode)
NSMenu.Item("Uninstall vChewing…")?.act(#selector(selfUninstall(_:))).nulled(silentMode || !optionKeyPressed)
}
}
}
// MARK: - IME Menu Items
public extension SessionCtl {
@objc override func showPreferences(_: Any? = nil) {
osCheck: if #available(macOS 13, *) {
switch NSEvent.keyModifierFlags {
case .option: break osCheck
default: CtlSettingsUI.show()
}
NSApp.popup()
return
}
CtlSettingsCocoa.show()
NSApp.popup()
}
@objc func showSettingsAppKit(_: Any? = nil) {
CtlSettingsCocoa.show()
NSApp.popup()
}
@available(macOS 13, *)
@objc func showSettingsSwiftUI(_: Any? = nil) {
CtlSettingsUI.show()
NSApp.popup()
}
@objc func showCheatSheet(_: Any? = nil) {
guard let url = Bundle.main.url(forResource: "shortcuts", withExtension: "html") else { return }
FileOpenMethod.safari.open(url: url)
}
@objc func showClientListMgr(_: Any? = nil) {
CtlClientListMgr.show()
NSApp.popup()
}
@objc func toggleCassetteMode(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
if !PrefMgr.shared.cassetteEnabled, !LMMgr.checkCassettePathValidity(PrefMgr.shared.cassettePath) {
DispatchQueue.main.async {
IMEApp.buzz()
let alert = NSAlert(error: "Path invalid or file access error.".localized)
let informativeText = "Please reconfigure the cassette path to a valid one before enabling this mode."
alert.informativeText = informativeText.localized
let result = alert.runModal()
NSApp.popup()
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
LMMgr.resetCassettePath()
PrefMgr.shared.cassetteEnabled = false
}
}
return
}
Notifier.notify(
message: "CIN Cassette Mode".localized + "\n"
+ (PrefMgr.shared.cassetteEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
if !inputMode.langModel.isCassetteDataLoaded {
LMMgr.loadCassetteData()
}
}
@objc func toggleSCPCTypingMode(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Per-Char Select Mode".localized + "\n"
+ (PrefMgr.shared.useSCPCTypingMode.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleChineseConverter(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Force KangXi Writing".localized + "\n"
+ (PrefMgr.shared.chineseConversionEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleShiftJISShinjitaiOutput(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "JIS Shinjitai Output".localized + "\n"
+ (PrefMgr.shared.shiftJISShinjitaiOutputEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleCurrencyNumerals(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Currency Numeral Output".localized + "\n"
+ (PrefMgr.shared.currencyNumeralsEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleHalfWidthPunctuation(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Half-Width Punctuation Mode".localized + "\n"
+ (PrefMgr.shared.halfWidthPunctuationEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleCNS11643Enabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "CNS11643 Mode".localized + "\n"
+ (PrefMgr.shared.cns11643Enabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleSymbolEnabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Symbol & Emoji Input".localized + "\n"
+ (PrefMgr.shared.symbolInputEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleAssociatedPhrasesEnabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Associated Phrases".localized + "\n"
+ (PrefMgr.shared.associatedPhrasesEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func togglePhraseReplacement(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Use Phrase Replacement".localized + "\n"
+ (PrefMgr.shared.phraseReplacementEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func selfUninstall(_: Any? = nil) {
AppDelegate.shared.selfUninstall()
}
@objc func selfTerminate(_: Any? = nil) {
NSApp.popup()
NSApp.terminate(nil)
}
@objc func checkForUpdate(_: Any? = nil) {
AppDelegate.shared.checkUpdate(forced: true) { [weak self] in
self?.clientBundleIdentifier == "com.apple.SecurityAgent"
}
}
@objc func openUserDataFolder(_: Any? = nil) {
guard LMMgr.userDataFolderExists else { return }
let url = URL(fileURLWithPath: LMMgr.dataFolderPath(isDefaultFolder: false))
FileOpenMethod.finder.open(url: url)
}
@objc func openAppSupportFolderFromContainer(_: Any? = nil) {
FileOpenMethod.finder.open(url: LMMgr.appSupportURL)
}
@objc func openUserPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .thePhrases, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openExcludedPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theFilter, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openUserSymbols(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theSymbols, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openPhraseReplacement(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theReplacements, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openAssociatedPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theAssociates, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func reloadUserPhrasesData(_: Any? = nil) {
LMMgr.initUserLangModels()
}
@objc func callReverseLookupWindow(_: Any? = nil) {
CtlRevLookupWindow.show()
}
@objc func removeUnigramsFromUOM(_: Any? = nil) {
LMMgr.removeUnigramsFromUserOverrideModel(IMEApp.currentInputMode)
LMMgr.removeUnigramsFromUserOverrideModel(IMEApp.currentInputMode.reversed)
}
@objc func clearUOM(_: Any? = nil) {
LMMgr.clearUserOverrideModelData(IMEApp.currentInputMode)
LMMgr.clearUserOverrideModelData(IMEApp.currentInputMode.reversed)
}
@objc func showAbout(_: Any? = nil) {
CtlAboutUI.show()
NSApp.popup()
}
}

View File

@ -1,445 +0,0 @@
// (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 AppKit
import MainAssembly
import NotifierUI
private extension Bool {
var state: NSControl.StateValue {
self ? .on : .off
}
}
// MARK: - IME Menu Manager
//
extension SessionCtl {
var optionKeyPressed: Bool { NSEvent.keyModifierFlags.contains(.option) }
override public func menu() -> NSMenu! {
let menu = NSMenu(title: "Input Method Menu")
var silentMode: Bool { clientBundleIdentifier == "com.apple.SecurityAgent" }
if PrefMgr.shared.isDebugModeEnabled, let currentMemorySizeInBytes = NSApplication.memoryFootprint {
let currentMemorySize: Double = (Double(currentMemorySizeInBytes) / 1024 / 1024).rounded(toPlaces: 1)
menu.addItem(withTitle: "Total RAM Usage: \(currentMemorySize)MB", action: nil, keyEquivalent: "")
}
let switchInputModeItem = menu.addItem(
withTitle: String(
format: "Switch to %@ Input Mode".localized,
IMEApp.currentInputMode.reversed.localizedDescription
),
action: #selector(switchInputMode(_:)), keyEquivalent: PrefMgr.shared.usingHotKeyInputMode ? "D" : ""
)
switchInputModeItem.keyEquivalentModifierMask = [.command, .control]
let useSCPCTypingModeItem = menu.addItem(
withTitle: "Per-Char Select Mode".localized,
action: #selector(toggleSCPCTypingMode(_:)), keyEquivalent: PrefMgr.shared.usingHotKeySCPC ? "P" : ""
)
useSCPCTypingModeItem.keyEquivalentModifierMask = [.command, .control]
useSCPCTypingModeItem.state = PrefMgr.shared.useSCPCTypingMode.state
let userAssociatedPhrasesItem = menu.addItem(
withTitle: "Associated Phrases".localized,
action: #selector(toggleAssociatedPhrasesEnabled(_:)),
keyEquivalent: PrefMgr.shared.usingHotKeyAssociates ? "O" : ""
)
userAssociatedPhrasesItem.keyEquivalentModifierMask = [.command, .control]
userAssociatedPhrasesItem.state = PrefMgr.shared.associatedPhrasesEnabled.state
let cassetteModeItem = menu.addItem(
withTitle: "CIN Cassette Mode".localized,
action: #selector(toggleCassetteMode(_:)),
keyEquivalent: PrefMgr.shared.usingHotKeyCassette ? "I" : ""
)
cassetteModeItem.keyEquivalentModifierMask = [.command, .control]
cassetteModeItem.state = PrefMgr.shared.cassetteEnabled.state
let useCNS11643SupportItem = menu.addItem(
withTitle: "CNS11643 Mode".localized,
action: #selector(toggleCNS11643Enabled(_:)), keyEquivalent: PrefMgr.shared.usingHotKeyCNS ? "L" : ""
)
useCNS11643SupportItem.keyEquivalentModifierMask = [.command, .control]
useCNS11643SupportItem.state = PrefMgr.shared.cns11643Enabled.state
if IMEApp.currentInputMode == .imeModeCHT {
let chineseConversionItem = menu.addItem(
withTitle: "Force KangXi Writing".localized,
action: #selector(toggleChineseConverter(_:)), keyEquivalent: PrefMgr.shared.usingHotKeyKangXi ? "K" : ""
)
chineseConversionItem.keyEquivalentModifierMask = [.command, .control]
chineseConversionItem.state = PrefMgr.shared.chineseConversionEnabled.state
let shiftJISConversionItem = menu.addItem(
withTitle: "JIS Shinjitai Output".localized,
action: #selector(toggleShiftJISShinjitaiOutput(_:)), keyEquivalent: PrefMgr.shared.usingHotKeyJIS ? "J" : ""
)
shiftJISConversionItem.keyEquivalentModifierMask = [.command, .control]
shiftJISConversionItem.state = PrefMgr.shared.shiftJISShinjitaiOutputEnabled.state
}
let currencyNumeralsItem = menu.addItem(
withTitle: "Currency Numeral Output".localized,
action: #selector(toggleCurrencyNumerals(_:)),
keyEquivalent: PrefMgr.shared.usingHotKeyCurrencyNumerals ? "M" : ""
)
currencyNumeralsItem.keyEquivalentModifierMask = [.command, .control]
currencyNumeralsItem.state = PrefMgr.shared.currencyNumeralsEnabled.state
let halfWidthPunctuationItem = menu.addItem(
withTitle: "Half-Width Punctuation Mode".localized,
action: #selector(toggleHalfWidthPunctuation(_:)),
keyEquivalent: PrefMgr.shared.usingHotKeyHalfWidthASCII ? "H" : ""
)
halfWidthPunctuationItem.keyEquivalentModifierMask = [.command, .control]
halfWidthPunctuationItem.state = PrefMgr.shared.halfWidthPunctuationEnabled.state
if optionKeyPressed || PrefMgr.shared.phraseReplacementEnabled {
let phaseReplacementItem = menu.addItem(
withTitle: "Use Phrase Replacement".localized,
action: #selector(togglePhraseReplacement(_:)), keyEquivalent: ""
)
phaseReplacementItem.state = PrefMgr.shared.phraseReplacementEnabled.state
}
if optionKeyPressed {
let toggleSymbolInputItem = menu.addItem(
withTitle: "Symbol & Emoji Input".localized,
action: #selector(toggleSymbolEnabled(_:)), keyEquivalent: ""
)
toggleSymbolInputItem.state = PrefMgr.shared.symbolInputEnabled.state
}
menu.addItem(NSMenuItem.separator()) // ---------------------
if !silentMode {
menu.addItem(
withTitle: "Open User Dictionary Folder".localized,
action: #selector(openUserDataFolder(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Edit vChewing User Phrases…".localized,
action: #selector(openUserPhrases(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Edit Excluded Phrases…".localized,
action: #selector(openExcludedPhrases(_:)), keyEquivalent: ""
)
if optionKeyPressed || PrefMgr.shared.associatedPhrasesEnabled {
menu.addItem(
withTitle: "Edit Associated Phrases…".localized,
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: ""
)
}
if optionKeyPressed {
menu.addItem(
withTitle: "Edit Phrase Replacement Table…".localized,
action: #selector(openPhraseReplacement(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Edit User Symbol & Emoji Data…".localized,
action: #selector(openUserSymbols(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Open App Support Folder".localized.withEllipsis,
action: #selector(openAppSupportFolderFromContainer(_:)), keyEquivalent: ""
)
}
}
if optionKeyPressed || !PrefMgr.shared.shouldAutoReloadUserDataFiles {
menu.addItem(
withTitle: "Reload User Phrases".localized,
action: #selector(reloadUserPhrasesData(_:)), keyEquivalent: ""
)
}
let revLookupMenuItem = menu.addItem(
withTitle: "Reverse Lookup (Phonabets)".localized.withEllipsis,
action: #selector(callReverseLookupWindow(_:)),
keyEquivalent: PrefMgr.shared.usingHotKeyRevLookup ? "/" : ""
)
revLookupMenuItem.keyEquivalentModifierMask = [.command, .control]
menu.addItem(
withTitle: "Optimize Memorized Phrases".localized,
action: #selector(removeUnigramsFromUOM(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Clear Memorized Phrases".localized,
action: #selector(clearUOM(_:)), keyEquivalent: ""
)
if !silentMode {
menu.addItem(NSMenuItem.separator()) // ---------------------
menu.addItem(
withTitle: "vChewing Preferences…".localized,
action: #selector(showPreferences(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "Client Manager".localized.withEllipsis,
action: #selector(showClientListMgr(_:)), keyEquivalent: ""
)
if !optionKeyPressed {
menu.addItem(
withTitle: "Check for Updates…".localized,
action: #selector(checkForUpdate(_:)), keyEquivalent: ""
)
}
menu.addItem(
withTitle: "Reboot vChewing…".localized,
action: #selector(selfTerminate(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "About vChewing…".localized,
action: #selector(showAbout(_:)), keyEquivalent: ""
)
menu.addItem(
withTitle: "CheatSheet".localized.withEllipsis,
action: #selector(showCheatSheet(_:)), keyEquivalent: ""
)
if optionKeyPressed {
menu.addItem(
withTitle: "Uninstall vChewing…".localized,
action: #selector(selfUninstall(_:)), keyEquivalent: ""
)
}
}
return menu
}
}
// MARK: - IME Menu Items
public extension SessionCtl {
@objc override func showPreferences(_: Any? = nil) {
osCheck: if #available(macOS 13, *) {
switch NSEvent.keyModifierFlags {
case .option: break osCheck
default: CtlSettingsUI.show()
}
NSApp.popup()
return
}
CtlSettingsCocoa.show()
NSApp.popup()
}
@objc func showCheatSheet(_: Any? = nil) {
guard let url = Bundle.main.url(forResource: "shortcuts", withExtension: "html") else { return }
guard let safariURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.Safari") else { return }
let configuration = NSWorkspace.OpenConfiguration()
configuration.promptsUserIfNeeded = true
NSWorkspace.shared.open([url], withApplicationAt: safariURL, configuration: configuration)
}
@objc func showClientListMgr(_: Any? = nil) {
CtlClientListMgr.show()
NSApp.popup()
}
@objc func toggleCassetteMode(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
if !PrefMgr.shared.cassetteEnabled, !LMMgr.checkCassettePathValidity(PrefMgr.shared.cassettePath) {
DispatchQueue.main.async {
IMEApp.buzz()
let alert = NSAlert(error: "Path invalid or file access error.".localized)
let informativeText = "Please reconfigure the cassette path to a valid one before enabling this mode."
alert.informativeText = informativeText.localized
let result = alert.runModal()
NSApp.popup()
if result == NSApplication.ModalResponse.alertFirstButtonReturn {
LMMgr.resetCassettePath()
PrefMgr.shared.cassetteEnabled = false
}
}
return
}
Notifier.notify(
message: "CIN Cassette Mode".localized + "\n"
+ (PrefMgr.shared.cassetteEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
if !inputMode.langModel.isCassetteDataLoaded {
LMMgr.loadCassetteData()
}
}
@objc func toggleSCPCTypingMode(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Per-Char Select Mode".localized + "\n"
+ (PrefMgr.shared.useSCPCTypingMode.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleChineseConverter(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Force KangXi Writing".localized + "\n"
+ (PrefMgr.shared.chineseConversionEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleShiftJISShinjitaiOutput(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "JIS Shinjitai Output".localized + "\n"
+ (PrefMgr.shared.shiftJISShinjitaiOutputEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleCurrencyNumerals(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Currency Numeral Output".localized + "\n"
+ (PrefMgr.shared.currencyNumeralsEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleHalfWidthPunctuation(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Half-Width Punctuation Mode".localized + "\n"
+ (PrefMgr.shared.halfWidthPunctuationEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleCNS11643Enabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "CNS11643 Mode".localized + "\n"
+ (PrefMgr.shared.cns11643Enabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleSymbolEnabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Symbol & Emoji Input".localized + "\n"
+ (PrefMgr.shared.symbolInputEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func toggleAssociatedPhrasesEnabled(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Associated Phrases".localized + "\n"
+ (PrefMgr.shared.associatedPhrasesEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func togglePhraseReplacement(_: Any? = nil) {
resetInputHandler(forceComposerCleanup: true)
Notifier.notify(
message: "Use Phrase Replacement".localized + "\n"
+ (PrefMgr.shared.phraseReplacementEnabled.toggled()
? "NotificationSwitchON".localized
: "NotificationSwitchOFF".localized)
)
}
@objc func selfUninstall(_: Any? = nil) {
AppDelegate.shared.selfUninstall()
}
@objc func selfTerminate(_: Any? = nil) {
NSApp.popup()
NSApp.terminate(nil)
}
@objc func checkForUpdate(_: Any? = nil) {
AppDelegate.shared.checkUpdate(forced: true) { [weak self] in
self?.clientBundleIdentifier == "com.apple.SecurityAgent"
}
}
@objc func openUserDataFolder(_: Any? = nil) {
if !LMMgr.userDataFolderExists {
return
}
let url = URL(fileURLWithPath: LMMgr.dataFolderPath(isDefaultFolder: false))
guard let finderURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.finder") else { return }
let configuration = NSWorkspace.OpenConfiguration()
configuration.promptsUserIfNeeded = true
NSWorkspace.shared.open([url], withApplicationAt: finderURL, configuration: configuration)
}
@objc func openAppSupportFolderFromContainer(_: Any? = nil) {
guard let finderURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.finder") else { return }
let configuration = NSWorkspace.OpenConfiguration()
configuration.promptsUserIfNeeded = true
NSWorkspace.shared.open([LMMgr.appSupportURL], withApplicationAt: finderURL, configuration: configuration)
}
@objc func openUserPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .thePhrases, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openExcludedPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theFilter, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openUserSymbols(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theSymbols, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openPhraseReplacement(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theReplacements, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func openAssociatedPhrases(_: Any? = nil) {
LMMgr.openUserDictFile(type: .theAssociates, dual: optionKeyPressed, alt: optionKeyPressed)
}
@objc func reloadUserPhrasesData(_: Any? = nil) {
LMMgr.initUserLangModels()
}
@objc func callReverseLookupWindow(_: Any? = nil) {
CtlRevLookupWindow.show()
}
@objc func removeUnigramsFromUOM(_: Any? = nil) {
LMMgr.removeUnigramsFromUserOverrideModel(IMEApp.currentInputMode)
LMMgr.removeUnigramsFromUserOverrideModel(IMEApp.currentInputMode.reversed)
}
@objc func clearUOM(_: Any? = nil) {
LMMgr.clearUserOverrideModelData(IMEApp.currentInputMode)
LMMgr.clearUserOverrideModelData(IMEApp.currentInputMode.reversed)
}
@objc func showAbout(_: Any? = nil) {
CtlAboutUI.show()
NSApp.popup()
}
}

View File

@ -23,7 +23,6 @@
5B98114828D6198700CBC605 /* PinyinPhonaConverter in Frameworks */ = {isa = PBXBuildFile; productRef = 5B98114728D6198700CBC605 /* PinyinPhonaConverter */; };
5BA8C30328DF0360004C5CC4 /* CandidateWindow in Frameworks */ = {isa = PBXBuildFile; productRef = 5BA8C30228DF0360004C5CC4 /* CandidateWindow */; };
5BAD0CD527D701F6003D127F /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
5BB802DA27FABA8300CF1C19 /* SessionCtl_Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB802D927FABA8300CF1C19 /* SessionCtl_Menu.swift */; };
5BBBB75F27AED54C0023B93A /* Beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75D27AED54C0023B93A /* Beep.m4a */; };
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75E27AED54C0023B93A /* Fart.m4a */; };
5BBC2D9E28F51C0400C986F6 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5B18BA7227C7BD8B0056EB19 /* LICENSE.txt */; };
@ -134,7 +133,6 @@
5B98114628D6198000CBC605 /* vChewing_PinyinPhonaConverter */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_PinyinPhonaConverter; path = Packages/vChewing_PinyinPhonaConverter; sourceTree = "<group>"; };
5BA8C30128DEFE4F004C5CC4 /* vChewing_CandidateWindow */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_CandidateWindow; path = Packages/vChewing_CandidateWindow; sourceTree = "<group>"; };
5BAD67E12ADAB62D005A4842 /* HangarRash_SwiftyCapsLockToggler */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = HangarRash_SwiftyCapsLockToggler; path = Packages/HangarRash_SwiftyCapsLockToggler; sourceTree = "<group>"; };
5BB802D927FABA8300CF1C19 /* SessionCtl_Menu.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = SessionCtl_Menu.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = "<group>"; };
5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = "<group>"; };
5BBC2DA228F5212100C986F6 /* RelocationDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelocationDetector.swift; sourceTree = "<group>"; };
@ -430,7 +428,6 @@
children = (
D427F76B278CA1BA004A2160 /* AppDelegateImpl.swift */,
D47B92BF27972AC800458394 /* main.swift */,
5BB802D927FABA8300CF1C19 /* SessionCtl_Menu.swift */,
);
path = Modules;
sourceTree = "<group>";
@ -709,7 +706,6 @@
files = (
D427F76C278CA2B0004A2160 /* AppDelegateImpl.swift in Sources */,
D47B92C027972AD100458394 /* main.swift in Sources */,
5BB802DA27FABA8300CF1C19 /* SessionCtl_Menu.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};