ctlIME // Extract all menu-related contents to a standalone file.
- Use a standalone swift file to manage the composition of the menu itself and its subcommands.
This commit is contained in:
parent
50c1928aea
commit
8cbae4a9d6
|
@ -31,6 +31,11 @@ import Cocoa
|
|||
// MARK: - 開關判定當前應用究竟是?
|
||||
@objc static var areWeUsingOurOwnPhraseEditor: Bool = false
|
||||
|
||||
// MARK: - 自 ctlInputMethod 讀取當前輸入法的簡繁體模式
|
||||
static func getInputMode() -> InputMode {
|
||||
return ctlInputMethod.currentKeyHandler.inputMode
|
||||
}
|
||||
|
||||
// MARK: - Print debug information to the console.
|
||||
@objc static func prtDebugIntel(_ strPrint: String) {
|
||||
if mgrPrefs.isDebugModeEnabled {
|
||||
|
@ -76,6 +81,30 @@ import Cocoa
|
|||
return false
|
||||
}
|
||||
|
||||
// MARK: - Open a phrase data file.
|
||||
static func openPhraseFile(userFileAt path: String) {
|
||||
func checkIfUserFilesExist() -> Bool {
|
||||
if !mgrLangModel.checkIfUserLanguageModelFilesExist() {
|
||||
let content = String(
|
||||
format: NSLocalizedString(
|
||||
"Please check the permission at \"%@\".", comment: ""),
|
||||
mgrLangModel.dataFolderPath(isDefaultFolder: false))
|
||||
ctlNonModalAlertWindow.shared.show(
|
||||
title: NSLocalizedString("Unable to create the user phrase file.", comment: ""),
|
||||
content: content, confirmButtonTitle: NSLocalizedString("OK", comment: ""),
|
||||
cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil)
|
||||
NSApp.setActivationPolicy(.accessory)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if !checkIfUserFilesExist() {
|
||||
return
|
||||
}
|
||||
NSWorkspace.shared.openFile(path, withApplication: "vChewingPhraseEditor")
|
||||
}
|
||||
|
||||
// MARK: - Trash a file if it exists.
|
||||
@discardableResult static func trashTargetIfExists(_ path: String) -> Bool {
|
||||
do {
|
||||
|
|
|
@ -27,12 +27,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
import Cocoa
|
||||
import InputMethodKit
|
||||
|
||||
extension Bool {
|
||||
fileprivate var state: NSControl.StateValue {
|
||||
self ? .on : .off
|
||||
}
|
||||
}
|
||||
|
||||
private let kMinKeyLabelSize: CGFloat = 10
|
||||
|
||||
private var ctlCandidateCurrent: ctlCandidate?
|
||||
|
@ -82,118 +76,6 @@ class ctlInputMethod: IMKInputController {
|
|||
keyHandler.delegate = self
|
||||
}
|
||||
|
||||
override func menu() -> NSMenu! {
|
||||
let optionKeyPressed = NSEvent.modifierFlags.contains(.option)
|
||||
|
||||
let menu = NSMenu(title: "Input Method Menu")
|
||||
|
||||
let useSCPCTypingModeItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Per-Char Select Mode", comment: ""),
|
||||
action: #selector(toggleSCPCTypingMode(_:)), keyEquivalent: "P")
|
||||
useSCPCTypingModeItem.keyEquivalentModifierMask = [.command, .control]
|
||||
useSCPCTypingModeItem.state = mgrPrefs.useSCPCTypingMode.state
|
||||
|
||||
let useCNS11643SupportItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("CNS11643 Mode", comment: ""),
|
||||
action: #selector(toggleCNS11643Enabled(_:)), keyEquivalent: "L")
|
||||
useCNS11643SupportItem.keyEquivalentModifierMask = [.command, .control]
|
||||
useCNS11643SupportItem.state = mgrPrefs.cns11643Enabled.state
|
||||
|
||||
if keyHandler.inputMode == InputMode.imeModeCHT {
|
||||
let chineseConversionItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Force KangXi Writing", comment: ""),
|
||||
action: #selector(toggleChineseConverter(_:)), keyEquivalent: "K")
|
||||
chineseConversionItem.keyEquivalentModifierMask = [.command, .control]
|
||||
chineseConversionItem.state = mgrPrefs.chineseConversionEnabled.state
|
||||
|
||||
let shiftJISConversionItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("JIS Shinjitai Output", comment: ""),
|
||||
action: #selector(toggleShiftJISShinjitaiOutput(_:)), keyEquivalent: "J")
|
||||
shiftJISConversionItem.keyEquivalentModifierMask = [.command, .control]
|
||||
shiftJISConversionItem.state = mgrPrefs.shiftJISShinjitaiOutputEnabled.state
|
||||
}
|
||||
|
||||
let halfWidthPunctuationItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Half-Width Punctuation Mode", comment: ""),
|
||||
action: #selector(toggleHalfWidthPunctuation(_:)), keyEquivalent: "H")
|
||||
halfWidthPunctuationItem.keyEquivalentModifierMask = [.command, .control]
|
||||
halfWidthPunctuationItem.state = mgrPrefs.halfWidthPunctuationEnabled.state
|
||||
|
||||
let userAssociatedPhrasesItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Per-Char Associated Phrases", comment: ""),
|
||||
action: #selector(toggleAssociatedPhrasesEnabled(_:)), keyEquivalent: "O")
|
||||
userAssociatedPhrasesItem.keyEquivalentModifierMask = [.command, .control]
|
||||
userAssociatedPhrasesItem.state = mgrPrefs.associatedPhrasesEnabled.state
|
||||
|
||||
if optionKeyPressed {
|
||||
let phaseReplacementItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Use Phrase Replacement", comment: ""),
|
||||
action: #selector(togglePhraseReplacement(_:)), keyEquivalent: "")
|
||||
phaseReplacementItem.state = mgrPrefs.phraseReplacementEnabled.state
|
||||
|
||||
let toggleSymbolInputItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Symbol & Emoji Input", comment: ""),
|
||||
action: #selector(toggleSymbolEnabled(_:)), keyEquivalent: "")
|
||||
toggleSymbolInputItem.state = mgrPrefs.symbolInputEnabled.state
|
||||
}
|
||||
|
||||
menu.addItem(NSMenuItem.separator()) // ---------------------
|
||||
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Open User Data Folder", comment: ""),
|
||||
action: #selector(openUserDataFolder(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit User Phrases…", comment: ""),
|
||||
action: #selector(openUserPhrases(_:)), keyEquivalent: "")
|
||||
|
||||
if optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Excluded Phrases…", comment: ""),
|
||||
action: #selector(openExcludedPhrases(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Phrase Replacement Table…", comment: ""),
|
||||
action: #selector(openPhraseReplacement(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
|
||||
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit User Symbol & Emoji Data…", comment: ""),
|
||||
action: #selector(openUserSymbols(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
if optionKeyPressed || !mgrPrefs.shouldAutoReloadUserDataFiles {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Reload User Phrases", comment: ""),
|
||||
action: #selector(reloadUserPhrases(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
menu.addItem(NSMenuItem.separator()) // ---------------------
|
||||
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("vChewing Preferences…", comment: ""),
|
||||
action: #selector(showPreferences(_:)), keyEquivalent: "")
|
||||
if !optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Check for Updates…", comment: ""),
|
||||
action: #selector(checkForUpdate(_:)), keyEquivalent: "")
|
||||
}
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Reboot vChewing…", comment: ""),
|
||||
action: #selector(selfTerminate(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("About vChewing…", comment: ""),
|
||||
action: #selector(showAbout(_:)), keyEquivalent: "")
|
||||
if optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Uninstall vChewing…", comment: ""),
|
||||
action: #selector(selfUninstall(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
// NSMenu 會阻止任何 modified key 相關的訊號傳回輸入法,所以咱們在此重設鍵盤佈局
|
||||
setKeyLayout()
|
||||
return menu
|
||||
}
|
||||
|
||||
// MARK: - IMKStateSetting protocol methods
|
||||
|
||||
override func activateServer(_ client: Any!) {
|
||||
|
@ -285,161 +167,6 @@ class ctlInputMethod: IMKInputController {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// MARK: - Menu Items
|
||||
|
||||
@objc override func showPreferences(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.showPreferences()
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
|
||||
@objc func toggleSCPCTypingMode(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Per-Char Select Mode", comment: ""), "\n",
|
||||
mgrPrefs.toggleSCPCTypingModeEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleChineseConverter(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Force KangXi Writing", comment: ""), "\n",
|
||||
mgrPrefs.toggleChineseConversionEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleShiftJISShinjitaiOutput(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("JIS Shinjitai Output", comment: ""), "\n",
|
||||
mgrPrefs.toggleShiftJISShinjitaiOutputEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleHalfWidthPunctuation(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Half-Width Punctuation Mode", comment: ""),
|
||||
"\n",
|
||||
mgrPrefs.toggleHalfWidthPunctuationEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleCNS11643Enabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("CNS11643 Mode", comment: ""), "\n",
|
||||
mgrPrefs.toggleCNS11643Enabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleSymbolEnabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Symbol & Emoji Input", comment: ""), "\n",
|
||||
mgrPrefs.toggleSymbolInputEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleAssociatedPhrasesEnabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Per-Char Associated Phrases", comment: ""),
|
||||
"\n",
|
||||
mgrPrefs.toggleAssociatedPhrasesEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func togglePhraseReplacement(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Use Phrase Replacement", comment: ""), "\n",
|
||||
mgrPrefs.togglePhraseReplacementEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func selfUninstall(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.selfUninstall()
|
||||
}
|
||||
|
||||
@objc func selfTerminate(_ sender: Any?) {
|
||||
NSApp.terminate(nil)
|
||||
}
|
||||
|
||||
@objc func checkForUpdate(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.checkForUpdate(forced: true)
|
||||
}
|
||||
|
||||
private func open(userFileAt path: String) {
|
||||
func checkIfUserFilesExist() -> Bool {
|
||||
if !mgrLangModel.checkIfUserLanguageModelFilesExist() {
|
||||
let content = String(
|
||||
format: NSLocalizedString(
|
||||
"Please check the permission at \"%@\".", comment: ""),
|
||||
mgrLangModel.dataFolderPath(isDefaultFolder: false))
|
||||
ctlNonModalAlertWindow.shared.show(
|
||||
title: NSLocalizedString("Unable to create the user phrase file.", comment: ""),
|
||||
content: content, confirmButtonTitle: NSLocalizedString("OK", comment: ""),
|
||||
cancelButtonTitle: nil, cancelAsDefault: false, delegate: nil)
|
||||
NSApp.setActivationPolicy(.accessory)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if !checkIfUserFilesExist() {
|
||||
return
|
||||
}
|
||||
NSWorkspace.shared.openFile(path, withApplication: "vChewingPhraseEditor")
|
||||
}
|
||||
|
||||
@objc func openUserPhrases(_ sender: Any?) {
|
||||
open(userFileAt: mgrLangModel.userPhrasesDataPath(keyHandler.inputMode))
|
||||
}
|
||||
|
||||
@objc func openUserDataFolder(_ sender: Any?) {
|
||||
if !mgrLangModel.checkIfUserDataFolderExists() {
|
||||
return
|
||||
}
|
||||
NSWorkspace.shared.openFile(
|
||||
mgrLangModel.dataFolderPath(isDefaultFolder: false), withApplication: "Finder")
|
||||
}
|
||||
|
||||
@objc func openExcludedPhrases(_ sender: Any?) {
|
||||
open(userFileAt: mgrLangModel.excludedPhrasesDataPath(keyHandler.inputMode))
|
||||
}
|
||||
|
||||
@objc func openUserSymbols(_ sender: Any?) {
|
||||
open(userFileAt: mgrLangModel.userSymbolDataPath(keyHandler.inputMode))
|
||||
}
|
||||
|
||||
@objc func openPhraseReplacement(_ sender: Any?) {
|
||||
open(userFileAt: mgrLangModel.phraseReplacementDataPath(keyHandler.inputMode))
|
||||
}
|
||||
|
||||
@objc func openAssociatedPhrases(_ sender: Any?) {
|
||||
open(userFileAt: mgrLangModel.userAssociatedPhrasesDataPath(keyHandler.inputMode))
|
||||
}
|
||||
|
||||
@objc func reloadUserPhrases(_ sender: Any?) {
|
||||
mgrLangModel.loadUserPhrases()
|
||||
mgrLangModel.loadUserPhraseReplacement()
|
||||
}
|
||||
|
||||
@objc func showAbout(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.showAbout()
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - State Handling
|
||||
|
|
|
@ -0,0 +1,282 @@
|
|||
// Copyright (c) 2011 and onwards The OpenVanilla Project (MIT License).
|
||||
// All possible vChewing-specific modifications are of:
|
||||
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
|
||||
/*
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
1. The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
2. 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 above.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import Cocoa
|
||||
|
||||
extension Bool {
|
||||
fileprivate var state: NSControl.StateValue {
|
||||
self ? .on : .off
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - IME Menu Manager
|
||||
// 因為選單部分的內容又臭又長,所以就單獨拉到一個檔案內管理了。
|
||||
|
||||
extension ctlInputMethod {
|
||||
override func menu() -> NSMenu! {
|
||||
let optionKeyPressed = NSEvent.modifierFlags.contains(.option)
|
||||
|
||||
let menu = NSMenu(title: "Input Method Menu")
|
||||
|
||||
let useSCPCTypingModeItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Per-Char Select Mode", comment: ""),
|
||||
action: #selector(toggleSCPCTypingMode(_:)), keyEquivalent: "P")
|
||||
useSCPCTypingModeItem.keyEquivalentModifierMask = [.command, .control]
|
||||
useSCPCTypingModeItem.state = mgrPrefs.useSCPCTypingMode.state
|
||||
|
||||
let userAssociatedPhrasesItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Per-Char Associated Phrases", comment: ""),
|
||||
action: #selector(toggleAssociatedPhrasesEnabled(_:)), keyEquivalent: "O")
|
||||
userAssociatedPhrasesItem.keyEquivalentModifierMask = [.command, .control]
|
||||
userAssociatedPhrasesItem.state = mgrPrefs.associatedPhrasesEnabled.state
|
||||
|
||||
let useCNS11643SupportItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("CNS11643 Mode", comment: ""),
|
||||
action: #selector(toggleCNS11643Enabled(_:)), keyEquivalent: "L")
|
||||
useCNS11643SupportItem.keyEquivalentModifierMask = [.command, .control]
|
||||
useCNS11643SupportItem.state = mgrPrefs.cns11643Enabled.state
|
||||
|
||||
if IME.getInputMode() == InputMode.imeModeCHT {
|
||||
let chineseConversionItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Force KangXi Writing", comment: ""),
|
||||
action: #selector(toggleChineseConverter(_:)), keyEquivalent: "K")
|
||||
chineseConversionItem.keyEquivalentModifierMask = [.command, .control]
|
||||
chineseConversionItem.state = mgrPrefs.chineseConversionEnabled.state
|
||||
|
||||
let shiftJISConversionItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("JIS Shinjitai Output", comment: ""),
|
||||
action: #selector(toggleShiftJISShinjitaiOutput(_:)), keyEquivalent: "J")
|
||||
shiftJISConversionItem.keyEquivalentModifierMask = [.command, .control]
|
||||
shiftJISConversionItem.state = mgrPrefs.shiftJISShinjitaiOutputEnabled.state
|
||||
}
|
||||
|
||||
let halfWidthPunctuationItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Half-Width Punctuation Mode", comment: ""),
|
||||
action: #selector(toggleHalfWidthPunctuation(_:)), keyEquivalent: "H")
|
||||
halfWidthPunctuationItem.keyEquivalentModifierMask = [.command, .control]
|
||||
halfWidthPunctuationItem.state = mgrPrefs.halfWidthPunctuationEnabled.state
|
||||
|
||||
if optionKeyPressed {
|
||||
let phaseReplacementItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Use Phrase Replacement", comment: ""),
|
||||
action: #selector(togglePhraseReplacement(_:)), keyEquivalent: "")
|
||||
phaseReplacementItem.state = mgrPrefs.phraseReplacementEnabled.state
|
||||
|
||||
let toggleSymbolInputItem = menu.addItem(
|
||||
withTitle: NSLocalizedString("Symbol & Emoji Input", comment: ""),
|
||||
action: #selector(toggleSymbolEnabled(_:)), keyEquivalent: "")
|
||||
toggleSymbolInputItem.state = mgrPrefs.symbolInputEnabled.state
|
||||
}
|
||||
|
||||
menu.addItem(NSMenuItem.separator()) // ---------------------
|
||||
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Open User Data Folder", comment: ""),
|
||||
action: #selector(openUserDataFolder(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit User Phrases…", comment: ""),
|
||||
action: #selector(openUserPhrases(_:)), keyEquivalent: "")
|
||||
|
||||
if optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Excluded Phrases…", comment: ""),
|
||||
action: #selector(openExcludedPhrases(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Phrase Replacement Table…", comment: ""),
|
||||
action: #selector(openPhraseReplacement(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit Associated Phrases…", comment: ""),
|
||||
action: #selector(openAssociatedPhrases(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Edit User Symbol & Emoji Data…", comment: ""),
|
||||
action: #selector(openUserSymbols(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
if optionKeyPressed || !mgrPrefs.shouldAutoReloadUserDataFiles {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Reload User Phrases", comment: ""),
|
||||
action: #selector(reloadUserPhrases(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
menu.addItem(NSMenuItem.separator()) // ---------------------
|
||||
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("vChewing Preferences…", comment: ""),
|
||||
action: #selector(showPreferences(_:)), keyEquivalent: "")
|
||||
if !optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Check for Updates…", comment: ""),
|
||||
action: #selector(checkForUpdate(_:)), keyEquivalent: "")
|
||||
}
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Reboot vChewing…", comment: ""),
|
||||
action: #selector(selfTerminate(_:)), keyEquivalent: "")
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("About vChewing…", comment: ""),
|
||||
action: #selector(showAbout(_:)), keyEquivalent: "")
|
||||
if optionKeyPressed {
|
||||
menu.addItem(
|
||||
withTitle: NSLocalizedString("Uninstall vChewing…", comment: ""),
|
||||
action: #selector(selfUninstall(_:)), keyEquivalent: "")
|
||||
}
|
||||
|
||||
// NSMenu 會阻止任何 modified key 相關的訊號傳回輸入法,所以咱們在此重設鍵盤佈局
|
||||
setKeyLayout()
|
||||
|
||||
return menu
|
||||
}
|
||||
|
||||
// MARK: - IME Menu Items
|
||||
|
||||
@objc override func showPreferences(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.showPreferences()
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
|
||||
@objc func toggleSCPCTypingMode(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Per-Char Select Mode", comment: ""), "\n",
|
||||
mgrPrefs.toggleSCPCTypingModeEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleChineseConverter(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Force KangXi Writing", comment: ""), "\n",
|
||||
mgrPrefs.toggleChineseConversionEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleShiftJISShinjitaiOutput(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("JIS Shinjitai Output", comment: ""), "\n",
|
||||
mgrPrefs.toggleShiftJISShinjitaiOutputEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleHalfWidthPunctuation(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Half-Width Punctuation Mode", comment: ""),
|
||||
"\n",
|
||||
mgrPrefs.toggleHalfWidthPunctuationEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleCNS11643Enabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("CNS11643 Mode", comment: ""), "\n",
|
||||
mgrPrefs.toggleCNS11643Enabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleSymbolEnabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Symbol & Emoji Input", comment: ""), "\n",
|
||||
mgrPrefs.toggleSymbolInputEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func toggleAssociatedPhrasesEnabled(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Per-Char Associated Phrases", comment: ""),
|
||||
"\n",
|
||||
mgrPrefs.toggleAssociatedPhrasesEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func togglePhraseReplacement(_ sender: Any?) {
|
||||
NotifierController.notify(
|
||||
message: String(
|
||||
format: "%@%@%@", NSLocalizedString("Use Phrase Replacement", comment: ""), "\n",
|
||||
mgrPrefs.togglePhraseReplacementEnabled()
|
||||
? NSLocalizedString("NotificationSwitchON", comment: "")
|
||||
: NSLocalizedString("NotificationSwitchOFF", comment: "")))
|
||||
}
|
||||
|
||||
@objc func selfUninstall(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.selfUninstall()
|
||||
}
|
||||
|
||||
@objc func selfTerminate(_ sender: Any?) {
|
||||
NSApp.terminate(nil)
|
||||
}
|
||||
|
||||
@objc func checkForUpdate(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.checkForUpdate(forced: true)
|
||||
}
|
||||
|
||||
@objc func openUserPhrases(_ sender: Any?) {
|
||||
IME.openPhraseFile(userFileAt: mgrLangModel.userPhrasesDataPath(IME.getInputMode()))
|
||||
}
|
||||
|
||||
@objc func openUserDataFolder(_ sender: Any?) {
|
||||
if !mgrLangModel.checkIfUserDataFolderExists() {
|
||||
return
|
||||
}
|
||||
NSWorkspace.shared.openFile(
|
||||
mgrLangModel.dataFolderPath(isDefaultFolder: false), withApplication: "Finder")
|
||||
}
|
||||
|
||||
@objc func openExcludedPhrases(_ sender: Any?) {
|
||||
IME.openPhraseFile(userFileAt: mgrLangModel.excludedPhrasesDataPath(IME.getInputMode()))
|
||||
}
|
||||
|
||||
@objc func openUserSymbols(_ sender: Any?) {
|
||||
IME.openPhraseFile(userFileAt: mgrLangModel.userSymbolDataPath(IME.getInputMode()))
|
||||
}
|
||||
|
||||
@objc func openPhraseReplacement(_ sender: Any?) {
|
||||
IME.openPhraseFile(userFileAt: mgrLangModel.phraseReplacementDataPath(IME.getInputMode()))
|
||||
}
|
||||
|
||||
@objc func openAssociatedPhrases(_ sender: Any?) {
|
||||
IME.openPhraseFile(userFileAt: mgrLangModel.userAssociatedPhrasesDataPath(IME.getInputMode()))
|
||||
}
|
||||
|
||||
@objc func reloadUserPhrases(_ sender: Any?) {
|
||||
mgrLangModel.loadUserPhrases()
|
||||
mgrLangModel.loadUserPhraseReplacement()
|
||||
}
|
||||
|
||||
@objc func showAbout(_ sender: Any?) {
|
||||
(NSApp.delegate as? AppDelegate)?.showAbout()
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
}
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
|
||||
5B7BC4B027AFFBE800F66C24 /* frmPrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */; };
|
||||
5BAD0CD527D701F6003D127F /* vChewingKeyLayout.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5B30F11227BA568800484E24 /* vChewingKeyLayout.bundle */; };
|
||||
5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */; };
|
||||
5BBBB75F27AED54C0023B93A /* Beep.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75D27AED54C0023B93A /* Beep.m4a */; };
|
||||
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB75E27AED54C0023B93A /* Fart.m4a */; };
|
||||
5BBBB76B27AED5DB0023B93A /* frmNonModalAlertWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5BBBB76527AED5DB0023B93A /* frmNonModalAlertWindow.xib */; };
|
||||
|
@ -187,6 +188,7 @@
|
|||
5B7BC4AF27AFFBE800F66C24 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Source/WindowNIBs/Base.lproj/frmPrefWindow.xib; sourceTree = "<group>"; };
|
||||
5B7BC4B227AFFC0B00F66C24 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Source/WindowNIBs/en.lproj/frmPrefWindow.strings; sourceTree = "<group>"; };
|
||||
5B8F43ED27C9BC220069AC27 /* SymbolLM.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SymbolLM.h; sourceTree = "<group>"; };
|
||||
5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_Menu.swift; sourceTree = "<group>"; };
|
||||
5BBBB75D27AED54C0023B93A /* Beep.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Beep.m4a; sourceTree = "<group>"; };
|
||||
5BBBB75E27AED54C0023B93A /* Fart.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = Fart.m4a; sourceTree = "<group>"; };
|
||||
5BBBB76627AED5DB0023B93A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/frmNonModalAlertWindow.xib; sourceTree = "<group>"; };
|
||||
|
@ -409,6 +411,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D4A13D5927A59D5C003BE359 /* ctlInputMethod.swift */,
|
||||
5BB802D927FABA8300CF1C19 /* ctlInputMethod_Menu.swift */,
|
||||
5B62A33127AE792F00A19448 /* InputSourceHelper.swift */,
|
||||
5B62A33527AE795800A19448 /* mgrPrefs.swift */,
|
||||
);
|
||||
|
@ -990,6 +993,7 @@
|
|||
5BF8423127BAA942008E7E4C /* vChewingKanjiConverter.swift in Sources */,
|
||||
5B62A34627AE7CD900A19448 /* ctlCandidateHorizontal.swift in Sources */,
|
||||
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */,
|
||||
5BB802DA27FABA8300CF1C19 /* ctlInputMethod_Menu.swift in Sources */,
|
||||
D41355DE278EA3ED005E5CBD /* UserPhrasesLM.mm in Sources */,
|
||||
6ACC3D3F27914F2400F1B140 /* KeyValueBlobReader.cpp in Sources */,
|
||||
D41355D8278D74B5005E5CBD /* mgrLangModel.mm in Sources */,
|
||||
|
|
Loading…
Reference in New Issue