1.9.1 SP2 // Maintenance. Merge Gitee PR!81 from upd/1.9.1sp2

This commit is contained in:
ShikiSuen 2022-08-11 05:31:13 +00:00 committed by Gitee
commit a227fa8459
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
39 changed files with 567 additions and 344 deletions

View File

@ -8,7 +8,7 @@ import SwiftUI
// MARK: - NSComboBox // MARK: - NSComboBox
// Ref: https://stackoverflow.com/a/71058587/4162914 // Ref: https://stackoverflow.com/a/71058587/4162914
@available(macOS 11.0, *) @available(macOS 10.15, *)
struct ComboBox: NSViewRepresentable { struct ComboBox: NSViewRepresentable {
// The items that will show up in the pop-up menu: // The items that will show up in the pop-up menu:
var items: [String] var items: [String]

@ -1 +1 @@
Subproject commit 1d1224ee392d757526dc8aab6550e9d41dd3d784 Subproject commit 1daf4d576a248373889889213bea4bd3cbb4b5d4

View File

@ -372,7 +372,6 @@ extension KeyHandler {
// MARK: Shift+ (Shift+Letter Processing) // MARK: Shift+ (Shift+Letter Processing)
// 使 2.2
if input.isUpperCaseASCIILetterKey, !input.isCommandHold, !input.isControlHold { if input.isUpperCaseASCIILetterKey, !input.isCommandHold, !input.isControlHold {
if input.isShiftHold { // isOptionHold if input.isShiftHold { // isOptionHold
switch mgrPrefs.upperCaseLetterKeyBehavior { switch mgrPrefs.upperCaseLetterKeyBehavior {
@ -388,7 +387,8 @@ extension KeyHandler {
return true return true
default: // case 0 default: // case 0
let letter: String! = String( let letter: String! = String(
format: "%@%c", "_letter_", charCode.isPrintableASCII ? CChar(charCode) : inputText) format: "%@%c", "_letter_", charCode.isPrintableASCII ? CChar(charCode) : inputText
)
if handlePunctuation( if handlePunctuation(
letter, letter,
state: state, state: state,

View File

@ -922,7 +922,8 @@ public struct Tekkon {
/// - newToneOne: /// - newToneOne:
/// - Returns: /// - Returns:
static func cnvHanyuPinyinToPhona(target: String, newToneOne: String = "") -> String { static func cnvHanyuPinyinToPhona(target: String, newToneOne: String = "") -> String {
if target.contains("_") { return target } ///
if target.contains("_") || !target.isNotPureAlphanumerical { return target }
var result = target var result = target
for key in Tekkon.mapHanyuPinyin.keys.sorted(by: { $0.count > $1.count }) { for key in Tekkon.mapHanyuPinyin.keys.sorted(by: { $0.count > $1.count }) {
guard let value = Tekkon.mapHanyuPinyin[key] else { continue } guard let value = Tekkon.mapHanyuPinyin[key] else { continue }
@ -1446,3 +1447,12 @@ public struct Tekkon {
"s": "", "t": "", "u": "", "v": "", "w": "", "x": "", "y": "", "z": "", " ": " ", "s": "", "t": "", "u": "", "v": "", "w": "", "x": "", "y": "", "z": "", " ": " ",
] ]
} }
///
extension String {
fileprivate var isNotPureAlphanumerical: Bool {
let regex = ".*[^A-Za-z0-9].*"
let testString = NSPredicate(format: "SELF MATCHES %@", regex)
return testString.evaluate(with: self)
}
}

View File

@ -187,7 +187,8 @@ class ctlInputMethod: IMKInputController {
@objc(handleEvent:client:) override func handle(_ event: NSEvent!, client sender: Any!) -> Bool { @objc(handleEvent:client:) override func handle(_ event: NSEvent!, client sender: Any!) -> Bool {
_ = sender // _ = sender //
// Shift // Shift macOS 10.15 macOS
if #available(macOS 10.15, *) {
if ShiftKeyUpChecker.check(event) { if ShiftKeyUpChecker.check(event) {
if !rencentKeyHandledByKeyHandler { if !rencentKeyHandledByKeyHandler {
NotifierController.notify( NotifierController.notify(
@ -202,6 +203,7 @@ class ctlInputMethod: IMKInputController {
rencentKeyHandledByKeyHandler = false rencentKeyHandledByKeyHandler = false
return false return false
} }
}
/// flags使 KeyHandler /// flags使 KeyHandler
/// flags /// flags

View File

@ -83,8 +83,23 @@ extension ctlInputMethod {
return NSFont.systemFont(ofSize: size) return NSFont.systemFont(ofSize: size)
} }
/// FB10978412: Since macOS 11 Big Sur, CTFontCreateUIFontForLanguage cannot
/// distinguish zh-Hans and zh-Hant with correct adoptation of proper PingFang SC/TC variants.
///
/// Instructions for Apple Developer relations to reveal this bug:
///
/// 1) Remove the usage of ".languageIdentifier" from ctlCandidateUniversal.swift (already done).
/// 2) Run "make update" in the project folder to download the latest git-submodule of dictionary file.
/// 3) Compile the target "vChewingInstaller", run it. It will install the input method into
/// "~/Library/Input Methods/" folder. Remember to ENABLE BOTH "vChewing-CHS"
/// and "vChewing-CHT" input sources in System Preferences / Settings.
/// 4) Type Zhuyin "ej3" (ˇ) (or "gu3" in Pinyin if you enabled Pinyin typing in vChewing preferences.)
/// using both "vChewing-CHS" and "vChewing-CHT", and check the candidate window by pressing SPACE key.
/// 5) Do NOT enable either KangXi conversion mode nor JIS conversion mode. They are disabled by default.
/// 6) Expecting the glyph differences of the candidate "" between PingFang SC and PingFang TC when rendering
/// the candidate window in different "vChewing-CHS" and "vChewing-CHT" input modes.
func candidateFont(name: String?, size: CGFloat) -> NSFont { func candidateFont(name: String?, size: CGFloat) -> NSFont {
var finalReturnFont: NSFont = let finalReturnFont: NSFont =
{ {
switch IME.currentInputMode { switch IME.currentInputMode {
case InputMode.imeModeCHS: case InputMode.imeModeCHS:
@ -98,9 +113,6 @@ extension ctlInputMethod {
} }
}() }()
?? NSFont.systemFont(ofSize: size) ?? NSFont.systemFont(ofSize: size)
// macOS 10.11-10.15 macOS 12 Monterey Bug
// macOS 12 Monterey ctlCandidateUniversal
if #available(macOS 12.0, *) { finalReturnFont = NSFont.systemFont(ofSize: size) }
if let name = name { if let name = name {
return NSFont(name: name, size: size) ?? finalReturnFont return NSFont(name: name, size: size) ?? finalReturnFont
} }

View File

@ -185,7 +185,7 @@ extension ctlInputMethod {
// MARK: - IME Menu Items // MARK: - IME Menu Items
@objc override func showPreferences(_: Any?) { @objc override func showPreferences(_: Any?) {
if #available(macOS 11.0, *) { if #available(macOS 10.15, *) {
NSApp.setActivationPolicy(.accessory) NSApp.setActivationPolicy(.accessory)
ctlPrefUI.shared.controller.show(preferencePane: Preferences.PaneIdentifier(rawValue: "General")) ctlPrefUI.shared.controller.show(preferencePane: Preferences.PaneIdentifier(rawValue: "General"))
ctlPrefUI.shared.controller.window?.level = .floating ctlPrefUI.shared.controller.window?.level = .floating

View File

@ -77,8 +77,15 @@ public enum IME {
// mgrLangModel loadUserPhrases dataFolderPath // mgrLangModel loadUserPhrases dataFolderPath
// //
// //
if mgrPrefs.associatedPhrasesEnabled {
mgrLangModel.loadUserAssociatesData() mgrLangModel.loadUserAssociatesData()
}
if mgrPrefs.phraseReplacementEnabled {
mgrLangModel.loadUserPhraseReplacement() mgrLangModel.loadUserPhraseReplacement()
}
if mgrPrefs.useSCPCTypingMode {
mgrLangModel.loadUserSCPCSequencesData()
}
mgrLangModel.loadUserPhrasesData() mgrLangModel.loadUserPhrasesData()
if !userOnly { if !userOnly {
// mgrLangModel.loadDataModels() // mgrLangModel.loadDataModels()

View File

@ -23,7 +23,7 @@ public enum UserDef: String, CaseIterable {
case kCandidateListTextSize = "CandidateListTextSize" case kCandidateListTextSize = "CandidateListTextSize"
case kAppleLanguages = "AppleLanguages" case kAppleLanguages = "AppleLanguages"
case kShouldAutoReloadUserDataFiles = "ShouldAutoReloadUserDataFiles" case kShouldAutoReloadUserDataFiles = "ShouldAutoReloadUserDataFiles"
case kUseRearCursorMode = "useRearCursorMode" case kUseRearCursorMode = "UseRearCursorMode"
case kUseHorizontalCandidateList = "UseHorizontalCandidateList" case kUseHorizontalCandidateList = "UseHorizontalCandidateList"
case kChooseCandidateUsingSpace = "ChooseCandidateUsingSpace" case kChooseCandidateUsingSpace = "ChooseCandidateUsingSpace"
case kCNS11643Enabled = "CNS11643Enabled" case kCNS11643Enabled = "CNS11643Enabled"
@ -388,15 +388,6 @@ public enum mgrPrefs {
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2 mgrPrefs.allowBoostingSingleKanjiAsUserPhrase ? 1 : 2
} }
@UserDefault(key: UserDef.kUseSCPCTypingMode.rawValue, defaultValue: false)
static var useSCPCTypingMode: Bool
static func toggleSCPCTypingModeEnabled() -> Bool {
useSCPCTypingMode = !useSCPCTypingMode
UserDefaults.standard.set(useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode.rawValue)
return useSCPCTypingMode
}
@UserDefault(key: UserDef.kMaxCandidateLength.rawValue, defaultValue: 10) @UserDefault(key: UserDef.kMaxCandidateLength.rawValue, defaultValue: 10)
static var maxCandidateLength: Int static var maxCandidateLength: Int
@ -564,8 +555,29 @@ public enum mgrPrefs {
} }
} }
@UserDefault(key: UserDef.kUseSCPCTypingMode.rawValue, defaultValue: false)
static var useSCPCTypingMode: Bool {
willSet {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
mgrLangModel.loadUserSCPCSequencesData()
}
}
}
static func toggleSCPCTypingModeEnabled() -> Bool {
useSCPCTypingMode = !useSCPCTypingMode
UserDefaults.standard.set(useSCPCTypingMode, forKey: UserDef.kUseSCPCTypingMode.rawValue)
return useSCPCTypingMode
}
@UserDefault(key: UserDef.kPhraseReplacementEnabled.rawValue, defaultValue: false) @UserDefault(key: UserDef.kPhraseReplacementEnabled.rawValue, defaultValue: false)
static var phraseReplacementEnabled: Bool static var phraseReplacementEnabled: Bool {
willSet {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
mgrLangModel.loadUserPhraseReplacement()
}
}
}
static func togglePhraseReplacementEnabled() -> Bool { static func togglePhraseReplacementEnabled() -> Bool {
phraseReplacementEnabled = !phraseReplacementEnabled phraseReplacementEnabled = !phraseReplacementEnabled
@ -575,7 +587,13 @@ public enum mgrPrefs {
} }
@UserDefault(key: UserDef.kAssociatedPhrasesEnabled.rawValue, defaultValue: false) @UserDefault(key: UserDef.kAssociatedPhrasesEnabled.rawValue, defaultValue: false)
static var associatedPhrasesEnabled: Bool static var associatedPhrasesEnabled: Bool {
willSet {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
mgrLangModel.loadUserAssociatesData()
}
}
}
static func toggleAssociatedPhrasesEnabled() -> Bool { static func toggleAssociatedPhrasesEnabled() -> Bool {
associatedPhrasesEnabled = !associatedPhrasesEnabled associatedPhrasesEnabled = !associatedPhrasesEnabled

View File

@ -76,6 +76,7 @@ extension vChewing {
) )
var lmReplacements = LMReplacments() var lmReplacements = LMReplacments()
var lmAssociates = LMAssociates() var lmAssociates = LMAssociates()
var lmPlainBopomofo = LMPlainBopomofo()
// MARK: - // MARK: -
@ -166,6 +167,16 @@ extension vChewing {
} }
} }
public func loadUserSCPCSequencesData(path: String) {
if FileManager.default.isReadableFile(atPath: path) {
lmPlainBopomofo.close()
lmPlainBopomofo.open(path)
IME.prtDebugIntel("lmPlainBopomofo: \(lmPlainBopomofo.count) entries of data loaded from: \(path)")
} else {
IME.prtDebugIntel("lmPlainBopomofo: File access failure: \(path)")
}
}
// MARK: - // MARK: -
/// ///
@ -181,6 +192,11 @@ extension vChewing {
/// ///
var rawAllUnigrams: [Megrez.Unigram] = [] var rawAllUnigrams: [Megrez.Unigram] = []
// 使
if mgrPrefs.useSCPCTypingMode {
rawAllUnigrams += lmPlainBopomofo.valuesFor(key: key).map { Megrez.Unigram(value: $0, score: 0) }
}
// reversed 使 // reversed 使
// //
// rawUserUnigrams // rawUserUnigrams

View File

@ -32,7 +32,7 @@ extension vChewing {
} }
let arrTarget = target.dropLast().dropFirst().split(separator: ",") let arrTarget = target.dropLast().dropFirst().split(separator: ",")
guard arrTarget.count == 2 else { return target } guard arrTarget.count == 2 else { return target }
return "(\(Tekkon.cnvHanyuPinyinToPhona(target: String(arrTarget[0]))),\(arrTarget[1]))" return "(\(Tekkon.cnvHanyuPinyinToPhona(target: String(arrTarget[0]).lowercased())),\(arrTarget[1]))"
} }
@discardableResult public mutating func open(_ path: String) -> Bool { @discardableResult public mutating func open(_ path: String) -> Bool {

View File

@ -77,7 +77,7 @@ extension vChewing {
if !neta[0].isEmpty, !neta[1].isEmpty { if !neta[0].isEmpty, !neta[1].isEmpty {
let theKey = shouldReverse ? String(neta[1]) : String(neta[0]) let theKey = shouldReverse ? String(neta[1]) : String(neta[0])
let theValue = $0 let theValue = $0
rangeMap[Tekkon.cnvHanyuPinyinToPhona(target: theKey), default: []].append(theValue) rangeMap[Tekkon.cnvHanyuPinyinToPhona(target: theKey.lowercased()), default: []].append(theValue)
} }
} }
} }

View File

@ -0,0 +1,83 @@
// Copyright (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// StringView Ranges extension by (c) 2022 and onwards Isaac Xen (MIT 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
extension vChewing {
@frozen public struct LMPlainBopomofo {
var rangeMap: [String: String] = [:]
public var count: Int {
rangeMap.count
}
public init() {
rangeMap = [:]
}
public func isLoaded() -> Bool {
!rangeMap.isEmpty
}
@discardableResult public mutating func open(_ path: String) -> Bool {
if isLoaded() {
return false
}
do {
let rawData = try Data(contentsOf: URL(fileURLWithPath: path))
let rawPlist: [String: String] =
try PropertyListSerialization.propertyList(from: rawData, format: nil) as? [String: String] ?? .init()
rangeMap = rawPlist
} catch {
IME.prtDebugIntel("\(error)")
IME.prtDebugIntel("↑ Exception happened when reading data at: \(path).")
return false
}
return true
}
public mutating func close() {
if isLoaded() {
rangeMap.removeAll()
}
}
public func dump() {
// We remove this function in order to reduce out maintenance workload.
// This function will be implemented only if further hard-necessity comes.
}
public func valuesFor(key: String) -> [String] {
var pairs: [String] = []
if let arrRangeRecords: String = rangeMap[key] {
pairs.append(contentsOf: arrRangeRecords.map { String($0) })
}
var set = Set<String>()
return pairs.filter { set.insert($0).inserted }
}
public func hasValuesFor(key: String) -> Bool { rangeMap.keys.contains(key) }
}
}
// MARK: - StringView Ranges Extension (by Isaac Xen)
extension String {
fileprivate func ranges(splitBy separator: Element) -> [Range<String.Index>] {
var startIndex = startIndex
return split(separator: separator).reduce(into: []) { ranges, substring in
_ = range(of: substring, range: startIndex..<endIndex).map { range in
ranges.append(range)
startIndex = range.upperBound
}
}
}
}

View File

@ -175,6 +175,15 @@ enum mgrLangModel {
) )
} }
public static func loadUserSCPCSequencesData() {
gLangModelCHT.loadUserSCPCSequencesData(
path: mgrLangModel.userSCPCSequencesURL(InputMode.imeModeCHT).path
)
gLangModelCHS.loadUserSCPCSequencesData(
path: mgrLangModel.userSCPCSequencesURL(InputMode.imeModeCHS).path
)
}
public static func checkIfUserPhraseExist( public static func checkIfUserPhraseExist(
userPhrase: String, userPhrase: String,
mode: InputMode, mode: InputMode,
@ -256,6 +265,14 @@ enum mgrLangModel {
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName) return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
} }
/// 使
/// - Parameter mode:
/// - Returns: URL
static func userSCPCSequencesURL(_ mode: InputMode) -> URL {
let fileName = (mode == InputMode.imeModeCHT) ? "data-plain-bpmf-cht.plist" : "data-plain-bpmf-chs.plist"
return URL(fileURLWithPath: dataFolderPath(isDefaultFolder: false)).appendingPathComponent(fileName)
}
/// 使 /// 使
/// - Returns: URL /// - Returns: URL
static func userSymbolNodeDataURL() -> URL { static func userSymbolNodeDataURL() -> URL {
@ -311,6 +328,7 @@ enum mgrLangModel {
userAssociatesDataURL(mode), userAssociatesDataURL(mode),
populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT populateWithTemplate: mode == .imeModeCHS ? kTemplateNameUserAssociatesCHS : kTemplateNameUserAssociatesCHT
) )
|| !ensureFileExists(userSCPCSequencesURL(mode))
|| !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions) || !ensureFileExists(userFilteredDataURL(mode), populateWithTemplate: kTemplateNameUserExclusions)
|| !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements) || !ensureFileExists(userReplacementsDataURL(mode), populateWithTemplate: kTemplateNameUserReplacements)
|| !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases) || !ensureFileExists(userSymbolDataURL(mode), populateWithTemplate: kTemplateNameUserSymbolPhrases)

View File

@ -79,12 +79,8 @@ extension Megrez.Compositor {
// //
let begin: Int = location - min(location, Megrez.Compositor.maxSpanLength - 1) let begin: Int = location - min(location, Megrez.Compositor.maxSpanLength - 1)
for theLocation in begin..<location { for theLocation in begin..<location {
let (A, B): (Int, Int) = { let (A, B): (Int, Int) = (location - theLocation + 1, spans[theLocation].maxLength)
( guard A <= B else { continue }
min(location - theLocation + 1, spans[theLocation].maxLength),
max(location - theLocation + 1, spans[theLocation].maxLength)
)
}()
for theLength in A...B { for theLength in A...B {
guard let node = spans[theLocation].nodeOf(length: theLength) else { continue } guard let node = spans[theLocation].nodeOf(length: theLength) else { continue }
results.append(.init(node: node, spanIndex: theLocation)) results.append(.init(node: node, spanIndex: theLocation))

View File

@ -150,7 +150,7 @@
"Keyboard" = "Keyboard"; "Keyboard" = "Keyboard";
"Misc Settings:" = "Misc Settings:"; "Misc Settings:" = "Misc Settings:";
"MiTAC" = "MiTAC"; "MiTAC" = "MiTAC";
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." = "Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only."; "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only." = "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only.";
"Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter";
"Output Settings:" = "Output Settings:"; "Output Settings:" = "Output Settings:";
"Phonetic Parser:" = "Phonetic Parser:"; "Phonetic Parser:" = "Phonetic Parser:";

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -150,7 +150,7 @@
"Keyboard" = "Keyboard"; "Keyboard" = "Keyboard";
"Misc Settings:" = "Misc Settings:"; "Misc Settings:" = "Misc Settings:";
"MiTAC" = "MiTAC"; "MiTAC" = "MiTAC";
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." = "Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only."; "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only." = "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only.";
"Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"; "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter";
"Output Settings:" = "Output Settings:"; "Output Settings:" = "Output Settings:";
"Phonetic Parser:" = "Phonetic Parser:"; "Phonetic Parser:" = "Phonetic Parser:";

View File

@ -150,7 +150,7 @@
"Keyboard" = "配列設定"; "Keyboard" = "配列設定";
"Misc Settings:" = "他の設定:"; "Misc Settings:" = "他の設定:";
"MiTAC" = "神通配列"; "MiTAC" = "神通配列";
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外の英数キーボードは漢語弁音以外の配列に不適用。"; "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外の英数キーボードは漢語弁音以外の配列に不適用。";
"Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter で出すのを漢語弁音と変換"; "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter で出すのを漢語弁音と変換";
"Output Settings:" = "出力設定:"; "Output Settings:" = "出力設定:";
"Phonetic Parser:" = "注音配列:"; "Phonetic Parser:" = "注音配列:";

View File

@ -151,7 +151,7 @@
"Keyboard" = "键盘"; "Keyboard" = "键盘";
"Misc Settings:" = "杂项:"; "Misc Settings:" = "杂项:";
"MiTAC" = "神通排列"; "MiTAC" = "神通排列";
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外的英数布局是为了汉语拼音排列使用者而准备的。"; "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外的英数布局是为了汉语拼音排列使用者而准备的。";
"Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter 输出汉语拼音而非注音"; "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter 输出汉语拼音而非注音";
"Output Settings:" = "输出设定:"; "Output Settings:" = "输出设定:";
"Phonetic Parser:" = "注音排列:"; "Phonetic Parser:" = "注音排列:";

View File

@ -150,7 +150,7 @@
"Keyboard" = "鍵盤"; "Keyboard" = "鍵盤";
"Misc Settings:" = "雜項:"; "Misc Settings:" = "雜項:";
"MiTAC" = "神通排列"; "MiTAC" = "神通排列";
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外的英數佈局是為了漢語拼音排列使用者而準備的。"; "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only." = "QWERTY 以外的英數佈局是為了漢語拼音排列使用者而準備的。";
"Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter 輸出漢語拼音而非注音"; "Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter" = "Ctrl(+Alt)+CMD+Enter 輸出漢語拼音而非注音";
"Output Settings:" = "輸出設定:"; "Output Settings:" = "輸出設定:";
"Phonetic Parser:" = "注音排列:"; "Phonetic Parser:" = "注音排列:";

View File

@ -190,20 +190,6 @@ private class vwrCandidateUniversal: NSView {
} else { } else {
NSColor.controlBackgroundColor.setFill() NSColor.controlBackgroundColor.setFill()
} }
switch IME.currentInputMode {
case InputMode.imeModeCHS:
if #available(macOS 12.0, *) {
activeCandidateAttr[.languageIdentifier] = "zh-Hans" as AnyObject
}
case InputMode.imeModeCHT:
if #available(macOS 12.0, *) {
activeCandidateAttr[.languageIdentifier] =
(mgrPrefs.shiftJISShinjitaiOutputEnabled || mgrPrefs.chineseConversionEnabled)
? "ja" as AnyObject : "zh-Hant" as AnyObject
}
default:
break
}
NSBezierPath.fill(rctCandidateArea) NSBezierPath.fill(rctCandidateArea)
(keyLabels[index] as NSString).draw( (keyLabels[index] as NSString).draw(
in: rctLabel, withAttributes: activeCandidateIndexAttr in: rctLabel, withAttributes: activeCandidateIndexAttr
@ -260,20 +246,6 @@ private class vwrCandidateUniversal: NSView {
} else { } else {
NSColor.controlBackgroundColor.setFill() NSColor.controlBackgroundColor.setFill()
} }
switch IME.currentInputMode {
case InputMode.imeModeCHS:
if #available(macOS 12.0, *) {
activeCandidateAttr[.languageIdentifier] = "zh-Hans" as AnyObject
}
case InputMode.imeModeCHT:
if #available(macOS 12.0, *) {
activeCandidateAttr[.languageIdentifier] =
(mgrPrefs.shiftJISShinjitaiOutputEnabled || mgrPrefs.chineseConversionEnabled)
? "ja" as AnyObject : "zh-Hant" as AnyObject
}
default:
break
}
NSBezierPath.fill(rctCandidateArea) NSBezierPath.fill(rctCandidateArea)
(keyLabels[index] as NSString).draw( (keyLabels[index] as NSString).draw(
in: rctLabel, withAttributes: activeCandidateIndexAttr in: rctLabel, withAttributes: activeCandidateIndexAttr

View File

@ -7,48 +7,59 @@
// requirements defined in MIT License. // requirements defined in MIT License.
import Cocoa import Cocoa
import SwiftUI
@available(macOS 11.0, *) @available(macOS 10.15, *)
class ctlPrefUI { class ctlPrefUI {
private(set) var tabImageGeneral: NSImage! = NSImage(named: "PrefToolbar-General")
private(set) var tabImageExperiences: NSImage! = NSImage(named: "PrefToolbar-Experiences")
private(set) var tabImageDictionary: NSImage! = NSImage(named: "PrefToolbar-Dictionary")
private(set) var tabImageKeyboard: NSImage! = NSImage(named: "PrefToolbar-Keyboard")
init() {
if #available(macOS 11.0, *) {
tabImageGeneral = NSImage(
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences"
)
tabImageExperiences = NSImage(
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences"
)
tabImageDictionary = NSImage(
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences"
)
tabImageKeyboard = NSImage(
systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences"
)
}
}
lazy var controller = PreferencesWindowController( lazy var controller = PreferencesWindowController(
panes: [ panes: [
Preferences.Pane( Preferences.Pane(
identifier: Preferences.PaneIdentifier(rawValue: "General"), identifier: Preferences.PaneIdentifier(rawValue: "General"),
title: NSLocalizedString("General", comment: ""), title: NSLocalizedString("General", comment: ""),
toolbarIcon: NSImage( toolbarIcon: tabImageGeneral
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences"
)
?? NSImage(named: NSImage.homeTemplateName)!
) { ) {
suiPrefPaneGeneral() suiPrefPaneGeneral()
}, },
Preferences.Pane( Preferences.Pane(
identifier: Preferences.PaneIdentifier(rawValue: "Experiences"), identifier: Preferences.PaneIdentifier(rawValue: "Experiences"),
title: NSLocalizedString("Experience", comment: ""), title: NSLocalizedString("Experience", comment: ""),
toolbarIcon: NSImage( toolbarIcon: tabImageExperiences
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences"
)
?? NSImage(named: NSImage.listViewTemplateName)!
) { ) {
suiPrefPaneExperience() suiPrefPaneExperience()
}, },
Preferences.Pane( Preferences.Pane(
identifier: Preferences.PaneIdentifier(rawValue: "Dictionary"), identifier: Preferences.PaneIdentifier(rawValue: "Dictionary"),
title: NSLocalizedString("Dictionary", comment: ""), title: NSLocalizedString("Dictionary", comment: ""),
toolbarIcon: NSImage( toolbarIcon: tabImageDictionary
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences"
)
?? NSImage(named: NSImage.bookmarksTemplateName)!
) { ) {
suiPrefPaneDictionary() suiPrefPaneDictionary()
}, },
Preferences.Pane( Preferences.Pane(
identifier: Preferences.PaneIdentifier(rawValue: "Keyboard"), identifier: Preferences.PaneIdentifier(rawValue: "Keyboard"),
title: NSLocalizedString("Keyboard", comment: ""), title: NSLocalizedString("Keyboard", comment: ""),
toolbarIcon: NSImage( toolbarIcon: tabImageKeyboard
systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences"
)
?? NSImage(named: NSImage.actionTemplateName)!
) { ) {
suiPrefPaneKeyboard() suiPrefPaneKeyboard()
}, },
@ -57,3 +68,47 @@ class ctlPrefUI {
) )
static let shared = ctlPrefUI() static let shared = ctlPrefUI()
} }
// MARK: - Add "onChange" support.
// Ref: https://mjeld.com/swiftui-macos-10-15-toggle-onchange/
@available(macOS 10.15, *)
extension Binding {
public func onChange(_ action: @escaping () -> Void) -> Binding {
Binding(
get: {
wrappedValue
},
set: { newValue in
wrappedValue = newValue
action()
}
)
}
}
// MARK: - Add ".tooltip" support.
// Ref: https://stackoverflow.com/a/63217861
@available(macOS 10.15, *)
struct Tooltip: NSViewRepresentable {
let tooltip: String
func makeNSView(context _: NSViewRepresentableContext<Tooltip>) -> NSView {
let view = NSView()
view.toolTip = tooltip
return view
}
func updateNSView(_: NSView, context _: NSViewRepresentableContext<Tooltip>) {}
}
@available(macOS 10.15, *)
extension View {
public func toolTip(_ tooltip: String) -> some View {
overlay(Tooltip(tooltip: tooltip))
}
}

View File

@ -8,7 +8,7 @@
import SwiftUI import SwiftUI
@available(macOS 11.0, *) @available(macOS 10.15, *)
struct suiPrefPaneDictionary: View { struct suiPrefPaneDictionary: View {
private var fdrDefault = mgrLangModel.dataFolderPath(isDefaultFolder: true) private var fdrDefault = mgrLangModel.dataFolderPath(isDefaultFolder: true)
@State private var tbxUserDataPathSpecified: String = @State private var tbxUserDataPathSpecified: String =
@ -43,8 +43,13 @@ struct suiPrefPaneDictionary: View {
Preferences.Section(title: "", bottomDivider: true) { Preferences.Section(title: "", bottomDivider: true) {
Text(LocalizedStringKey("Choose your desired user data folder path. Will be omitted if invalid.")) Text(LocalizedStringKey("Choose your desired user data folder path. Will be omitted if invalid."))
HStack { HStack {
if #available(macOS 11.0, *) {
TextField(fdrDefault, text: $tbxUserDataPathSpecified).disabled(true) TextField(fdrDefault, text: $tbxUserDataPathSpecified).disabled(true)
.help(tbxUserDataPathSpecified) .help(tbxUserDataPathSpecified)
} else {
TextField(fdrDefault, text: $tbxUserDataPathSpecified).disabled(true)
.toolTip(tbxUserDataPathSpecified)
}
Button { Button {
IME.dlgOpenPath.title = NSLocalizedString( IME.dlgOpenPath.title = NSLocalizedString(
"Choose your desired user data folder.", comment: "" "Choose your desired user data folder.", comment: ""
@ -98,48 +103,43 @@ struct suiPrefPaneDictionary: View {
} }
Toggle( Toggle(
LocalizedStringKey("Automatically reload user data files if changes detected"), LocalizedStringKey("Automatically reload user data files if changes detected"),
isOn: $selAutoReloadUserData isOn: $selAutoReloadUserData.onChange {
).controlSize(.small).onChange(of: selAutoReloadUserData) { value in mgrPrefs.shouldAutoReloadUserDataFiles = selAutoReloadUserData
mgrPrefs.shouldAutoReloadUserDataFiles = value
} }
).controlSize(.small)
Divider() Divider()
Toggle( Toggle(
LocalizedStringKey("Enable CNS11643 Support (2022-07-20)"), LocalizedStringKey("Enable CNS11643 Support (2022-07-20)"),
isOn: $selEnableCNS11643 isOn: $selEnableCNS11643.onChange {
) mgrPrefs.cns11643Enabled = selEnableCNS11643
.onChange(of: selEnableCNS11643) { value in mgrLangModel.setCNSEnabled(mgrPrefs.cns11643Enabled)
mgrPrefs.cns11643Enabled = value
mgrLangModel.setCNSEnabled(value)
} }
)
Toggle( Toggle(
LocalizedStringKey("Enable symbol input support (incl. certain emoji symbols)"), LocalizedStringKey("Enable symbol input support (incl. certain emoji symbols)"),
isOn: $selEnableSymbolInputSupport isOn: $selEnableSymbolInputSupport.onChange {
) mgrPrefs.symbolInputEnabled = selEnableSymbolInputSupport
.onChange(of: selEnableSymbolInputSupport) { value in mgrLangModel.setSymbolEnabled(mgrPrefs.symbolInputEnabled)
mgrPrefs.symbolInputEnabled = value
mgrLangModel.setSymbolEnabled(value)
} }
)
Toggle( Toggle(
LocalizedStringKey("Allow boosting / excluding a candidate of single kanji"), LocalizedStringKey("Allow boosting / excluding a candidate of single kanji"),
isOn: $selAllowBoostingSingleKanjiAsUserPhrase isOn: $selAllowBoostingSingleKanjiAsUserPhrase.onChange {
) mgrPrefs.allowBoostingSingleKanjiAsUserPhrase = selAllowBoostingSingleKanjiAsUserPhrase
.onChange(of: selAllowBoostingSingleKanjiAsUserPhrase) { value in
mgrPrefs.allowBoostingSingleKanjiAsUserPhrase = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Applying typing suggestions from half-life user override model"), LocalizedStringKey("Applying typing suggestions from half-life user override model"),
isOn: $selFetchSuggestionsFromUserOverrideModel isOn: $selFetchSuggestionsFromUserOverrideModel.onChange {
) mgrPrefs.fetchSuggestionsFromUserOverrideModel = selFetchSuggestionsFromUserOverrideModel
.onChange(of: selFetchSuggestionsFromUserOverrideModel) { value in
mgrPrefs.fetchSuggestionsFromUserOverrideModel = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Always use fixed listing order in candidate window"), LocalizedStringKey("Always use fixed listing order in candidate window"),
isOn: $selUseFixecCandidateOrderOnSelection isOn: $selUseFixecCandidateOrderOnSelection.onChange {
) mgrPrefs.useFixecCandidateOrderOnSelection = selUseFixecCandidateOrderOnSelection
.onChange(of: selUseFixecCandidateOrderOnSelection) { value in
mgrPrefs.useFixecCandidateOrderOnSelection = value
} }
)
} }
} }
} }

View File

@ -9,11 +9,8 @@
import Cocoa import Cocoa
import SwiftUI import SwiftUI
@available(macOS 11.0, *) @available(macOS 10.15, *)
struct suiPrefPaneExperience: View { struct suiPrefPaneExperience: View {
@State private var selSelectionKeysList = mgrPrefs.suggestedCandidateKeys
@State private var selSelectionKeys =
(UserDefaults.standard.string(forKey: UserDef.kCandidateKeys.rawValue) ?? mgrPrefs.defaultCandidateKeys) as String
@State private var selCursorPosition = @State private var selCursorPosition =
UserDefaults.standard.bool( UserDefaults.standard.bool(
forKey: UserDef.kUseRearCursorMode.rawValue) ? 1 : 0 forKey: UserDef.kUseRearCursorMode.rawValue) ? 1 : 0
@ -54,40 +51,15 @@ struct suiPrefPaneExperience: View {
var body: some View { var body: some View {
Preferences.Container(contentWidth: contentWidth) { Preferences.Container(contentWidth: contentWidth) {
Preferences.Section(label: { Text(LocalizedStringKey("Selection Keys:")) }) {
ComboBox(items: mgrPrefs.suggestedCandidateKeys, text: $selSelectionKeys).frame(width: 180).onChange(
of: selSelectionKeys
) { value in
let keys: String = value.trimmingCharacters(in: .whitespacesAndNewlines).deduplicate
do {
try mgrPrefs.validate(candidateKeys: keys)
mgrPrefs.candidateKeys = keys
selSelectionKeys = mgrPrefs.candidateKeys
} catch mgrPrefs.CandidateKeyError.empty {
selSelectionKeys = mgrPrefs.candidateKeys
} catch {
if let window = ctlPrefUI.shared.controller.window {
let alert = NSAlert(error: error)
alert.beginSheetModal(for: window) { _ in
selSelectionKeys = mgrPrefs.candidateKeys
}
clsSFX.beep()
}
}
}
Text(
LocalizedStringKey(
"Choose or hit Enter to confim your prefered keys for selecting candidates."
)
)
.preferenceDescription()
}
Preferences.Section(label: { Text(LocalizedStringKey("Cursor Selection:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("Cursor Selection:")) }) {
Picker("", selection: $selCursorPosition) { Picker(
"",
selection: $selCursorPosition.onChange {
mgrPrefs.useRearCursorMode = (selCursorPosition == 1) ? true : false
}
) {
Text(LocalizedStringKey("in front of the phrase (like macOS built-in Zhuyin IME)")).tag(0) Text(LocalizedStringKey("in front of the phrase (like macOS built-in Zhuyin IME)")).tag(0)
Text(LocalizedStringKey("at the rear of the phrase (like Microsoft New Phonetic)")).tag(1) Text(LocalizedStringKey("at the rear of the phrase (like Microsoft New Phonetic)")).tag(1)
}.onChange(of: selCursorPosition) { value in
mgrPrefs.useRearCursorMode = (value == 1) ? true : false
} }
.labelsHidden() .labelsHidden()
.pickerStyle(RadioGroupPickerStyle()) .pickerStyle(RadioGroupPickerStyle())
@ -95,17 +67,20 @@ struct suiPrefPaneExperience: View {
.preferenceDescription() .preferenceDescription()
Toggle( Toggle(
LocalizedStringKey("Push the cursor in front of the phrase after selection"), LocalizedStringKey("Push the cursor in front of the phrase after selection"),
isOn: $selPushCursorAfterSelection isOn: $selPushCursorAfterSelection.onChange {
).onChange(of: selPushCursorAfterSelection) { value in mgrPrefs.moveCursorAfterSelectingCandidate = selPushCursorAfterSelection
mgrPrefs.moveCursorAfterSelectingCandidate = value }
}.controlSize(.small) ).controlSize(.small)
} }
Preferences.Section(title: "(Shift+)Tab:") { Preferences.Section(title: "(Shift+)Tab:") {
Picker("", selection: $selKeyBehaviorShiftTab) { Picker(
"",
selection: $selKeyBehaviorShiftTab.onChange {
mgrPrefs.specifyShiftTabKeyBehavior = (selKeyBehaviorShiftTab == 1) ? true : false
}
) {
Text(LocalizedStringKey("for cycling candidates")).tag(0) Text(LocalizedStringKey("for cycling candidates")).tag(0)
Text(LocalizedStringKey("for cycling pages")).tag(1) Text(LocalizedStringKey("for cycling pages")).tag(1)
}.onChange(of: selKeyBehaviorShiftTab) { value in
mgrPrefs.specifyShiftTabKeyBehavior = (value == 1) ? true : false
} }
.labelsHidden() .labelsHidden()
.horizontalRadioGroupLayout() .horizontalRadioGroupLayout()
@ -114,11 +89,14 @@ struct suiPrefPaneExperience: View {
.preferenceDescription() .preferenceDescription()
} }
Preferences.Section(label: { Text(LocalizedStringKey("(Shift+)Space:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("(Shift+)Space:")) }) {
Picker("", selection: $selKeyBehaviorShiftSpace) { Picker(
"",
selection: $selKeyBehaviorShiftSpace.onChange {
mgrPrefs.specifyShiftSpaceKeyBehavior = (selKeyBehaviorShiftSpace == 1) ? true : false
}
) {
Text(LocalizedStringKey("Space to +cycle candidates, Shift+Space to +cycle pages")).tag(0) Text(LocalizedStringKey("Space to +cycle candidates, Shift+Space to +cycle pages")).tag(0)
Text(LocalizedStringKey("Space to +cycle pages, Shift+Space to +cycle candidates")).tag(1) Text(LocalizedStringKey("Space to +cycle pages, Shift+Space to +cycle candidates")).tag(1)
}.onChange(of: selKeyBehaviorShiftSpace) { value in
mgrPrefs.specifyShiftSpaceKeyBehavior = (value == 1) ? true : false
} }
.labelsHidden() .labelsHidden()
.pickerStyle(RadioGroupPickerStyle()) .pickerStyle(RadioGroupPickerStyle())
@ -126,12 +104,15 @@ struct suiPrefPaneExperience: View {
.preferenceDescription() .preferenceDescription()
} }
Preferences.Section(label: { Text(LocalizedStringKey("Shift+Letter:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("Shift+Letter:")) }) {
Picker("", selection: $selUpperCaseLetterKeyBehavior) { Picker(
"",
selection: $selUpperCaseLetterKeyBehavior.onChange {
mgrPrefs.upperCaseLetterKeyBehavior = selUpperCaseLetterKeyBehavior
}
) {
Text(LocalizedStringKey("Type them into inline composition buffer")).tag(0) Text(LocalizedStringKey("Type them into inline composition buffer")).tag(0)
Text(LocalizedStringKey("Directly commit lowercased letters")).tag(1) Text(LocalizedStringKey("Directly commit lowercased letters")).tag(1)
Text(LocalizedStringKey("Directly commit uppercased letters")).tag(2) Text(LocalizedStringKey("Directly commit uppercased letters")).tag(2)
}.onChange(of: selUpperCaseLetterKeyBehavior) { value in
mgrPrefs.upperCaseLetterKeyBehavior = value
} }
.labelsHidden() .labelsHidden()
.pickerStyle(RadioGroupPickerStyle()) .pickerStyle(RadioGroupPickerStyle())
@ -141,39 +122,46 @@ struct suiPrefPaneExperience: View {
Preferences.Section(label: { Text(LocalizedStringKey("Misc Settings:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("Misc Settings:")) }) {
Toggle( Toggle(
LocalizedStringKey("Enable Space key for calling candidate window"), LocalizedStringKey("Enable Space key for calling candidate window"),
isOn: $selKeyBehaviorSpaceForCallingCandidate isOn: $selKeyBehaviorSpaceForCallingCandidate.onChange {
).onChange(of: selKeyBehaviorSpaceForCallingCandidate) { value in mgrPrefs.chooseCandidateUsingSpace = selKeyBehaviorSpaceForCallingCandidate
mgrPrefs.chooseCandidateUsingSpace = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Use ESC key to clear the entire input buffer"), LocalizedStringKey("Use ESC key to clear the entire input buffer"),
isOn: $selKeyBehaviorESCForClearingTheBuffer isOn: $selKeyBehaviorESCForClearingTheBuffer.onChange {
).onChange(of: selKeyBehaviorESCForClearingTheBuffer) { value in mgrPrefs.escToCleanInputBuffer = selKeyBehaviorESCForClearingTheBuffer
mgrPrefs.escToCleanInputBuffer = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Automatically correct reading combinations when typing"), LocalizedStringKey("Automatically correct reading combinations when typing"),
isOn: $selAutoCorrectReadingCombination isOn: $selAutoCorrectReadingCombination.onChange {
).onChange(of: selAutoCorrectReadingCombination) { value in mgrPrefs.autoCorrectReadingCombination = selAutoCorrectReadingCombination
mgrPrefs.autoCorrectReadingCombination = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Allow using Enter key to confirm associated candidate selection"), LocalizedStringKey("Allow using Enter key to confirm associated candidate selection"),
isOn: $selAlsoConfirmAssociatedCandidatesByEnter isOn: $selAlsoConfirmAssociatedCandidatesByEnter.onChange {
).onChange(of: selAlsoConfirmAssociatedCandidatesByEnter) { value in mgrPrefs.alsoConfirmAssociatedCandidatesByEnter = selAlsoConfirmAssociatedCandidatesByEnter
mgrPrefs.alsoConfirmAssociatedCandidatesByEnter = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Also toggle alphanumerical mode with Left-Shift"), LocalizedStringKey("Also toggle alphanumerical mode with Left-Shift"),
isOn: $selTogglingAlphanumericalModeWithLShift isOn: $selTogglingAlphanumericalModeWithLShift.onChange {
).onChange(of: selTogglingAlphanumericalModeWithLShift) { value in mgrPrefs.togglingAlphanumericalModeWithLShift = selTogglingAlphanumericalModeWithLShift
mgrPrefs.togglingAlphanumericalModeWithLShift = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Emulating select-candidate-per-character mode"), isOn: $selEnableSCPCTypingMode LocalizedStringKey("Allow backspace-editing miscomposed readings"),
).onChange(of: selEnableSCPCTypingMode) { value in isOn: $selKeepReadingUponCompositionError.onChange {
mgrPrefs.useSCPCTypingMode = value mgrPrefs.keepReadingUponCompositionError = selKeepReadingUponCompositionError
} }
)
Toggle(
LocalizedStringKey("Emulating select-candidate-per-character mode"),
isOn: $selEnableSCPCTypingMode.onChange {
mgrPrefs.useSCPCTypingMode = selEnableSCPCTypingMode
}
)
Text(LocalizedStringKey("An accomodation for elder computer users.")) Text(LocalizedStringKey("An accomodation for elder computer users."))
.preferenceDescription() .preferenceDescription()
} }

View File

@ -9,7 +9,7 @@
import Cocoa import Cocoa
import SwiftUI import SwiftUI
@available(macOS 11.0, *) @available(macOS 10.15, *)
struct suiPrefPaneGeneral: View { struct suiPrefPaneGeneral: View {
@State private var selCandidateUIFontSize = UserDefaults.standard.integer( @State private var selCandidateUIFontSize = UserDefaults.standard.integer(
forKey: UserDef.kCandidateListTextSize.rawValue) forKey: UserDef.kCandidateListTextSize.rawValue)
@ -53,7 +53,12 @@ struct suiPrefPaneGeneral: View {
var body: some View { var body: some View {
Preferences.Container(contentWidth: contentWidth) { Preferences.Container(contentWidth: contentWidth) {
Preferences.Section(bottomDivider: false, label: { Text(LocalizedStringKey("Candidate Size:")) }) { Preferences.Section(bottomDivider: false, label: { Text(LocalizedStringKey("Candidate Size:")) }) {
Picker("", selection: $selCandidateUIFontSize) { Picker(
"",
selection: $selCandidateUIFontSize.onChange {
mgrPrefs.candidateListTextSize = CGFloat(selCandidateUIFontSize)
}
) {
Text("12").tag(12) Text("12").tag(12)
Text("14").tag(14) Text("14").tag(14)
Text("16").tag(16) Text("16").tag(16)
@ -62,8 +67,6 @@ struct suiPrefPaneGeneral: View {
Text("32").tag(32) Text("32").tag(32)
Text("64").tag(64) Text("64").tag(64)
Text("96").tag(96) Text("96").tag(96)
}.onChange(of: selCandidateUIFontSize) { value in
mgrPrefs.candidateListTextSize = CGFloat(value)
} }
.labelsHidden() .labelsHidden()
.frame(width: 120.0) .frame(width: 120.0)
@ -71,14 +74,10 @@ struct suiPrefPaneGeneral: View {
.preferenceDescription() .preferenceDescription()
} }
Preferences.Section(bottomDivider: false, label: { Text(LocalizedStringKey("UI Language:")) }) { Preferences.Section(bottomDivider: false, label: { Text(LocalizedStringKey("UI Language:")) }) {
Picker(LocalizedStringKey("Follow OS settings"), selection: $selUILanguage) { Picker(
Text(LocalizedStringKey("Follow OS settings")).tag(["auto"]) LocalizedStringKey("Follow OS settings"),
Text(LocalizedStringKey("Simplified Chinese")).tag(["zh-Hans"]) selection: $selUILanguage.onChange {
Text(LocalizedStringKey("Traditional Chinese")).tag(["zh-Hant"]) IME.prtDebugIntel(selUILanguage[0])
Text(LocalizedStringKey("Japanese")).tag(["ja"])
Text(LocalizedStringKey("English")).tag(["en"])
}.onChange(of: selUILanguage) { value in
IME.prtDebugIntel(value[0])
if selUILanguage == mgrPrefs.appleLanguages if selUILanguage == mgrPrefs.appleLanguages
|| (selUILanguage[0] == "auto" || (selUILanguage[0] == "auto"
&& UserDefaults.standard.object(forKey: UserDef.kAppleLanguages.rawValue) == nil) && UserDefaults.standard.object(forKey: UserDef.kAppleLanguages.rawValue) == nil)
@ -86,13 +85,20 @@ struct suiPrefPaneGeneral: View {
return return
} }
if selUILanguage[0] != "auto" { if selUILanguage[0] != "auto" {
mgrPrefs.appleLanguages = value mgrPrefs.appleLanguages = selUILanguage
} else { } else {
UserDefaults.standard.removeObject(forKey: UserDef.kAppleLanguages.rawValue) UserDefaults.standard.removeObject(forKey: UserDef.kAppleLanguages.rawValue)
} }
NSLog("vChewing App self-terminated due to UI language change.") NSLog("vChewing App self-terminated due to UI language change.")
NSApplication.shared.terminate(nil) NSApplication.shared.terminate(nil)
} }
) {
Text(LocalizedStringKey("Follow OS settings")).tag(["auto"])
Text(LocalizedStringKey("Simplified Chinese")).tag(["zh-Hans"])
Text(LocalizedStringKey("Traditional Chinese")).tag(["zh-Hant"])
Text(LocalizedStringKey("Japanese")).tag(["ja"])
Text(LocalizedStringKey("English")).tag(["en"])
}
.labelsHidden() .labelsHidden()
.frame(width: 180.0) .frame(width: 180.0)
@ -100,11 +106,14 @@ struct suiPrefPaneGeneral: View {
.preferenceDescription() .preferenceDescription()
} }
Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Candidate Layout:")) }) { Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Candidate Layout:")) }) {
Picker("", selection: $selEnableHorizontalCandidateLayout) { Picker(
"",
selection: $selEnableHorizontalCandidateLayout.onChange {
mgrPrefs.useHorizontalCandidateList = selEnableHorizontalCandidateLayout
}
) {
Text(LocalizedStringKey("Vertical")).tag(false) Text(LocalizedStringKey("Vertical")).tag(false)
Text(LocalizedStringKey("Horizontal")).tag(true) Text(LocalizedStringKey("Horizontal")).tag(true)
}.onChange(of: selEnableHorizontalCandidateLayout) { value in
mgrPrefs.useHorizontalCandidateList = value
} }
.labelsHidden() .labelsHidden()
.horizontalRadioGroupLayout() .horizontalRadioGroupLayout()
@ -112,11 +121,9 @@ struct suiPrefPaneGeneral: View {
Text(LocalizedStringKey("Choose your preferred layout of the candidate window.")) Text(LocalizedStringKey("Choose your preferred layout of the candidate window."))
.preferenceDescription() .preferenceDescription()
Toggle( Toggle(
LocalizedStringKey("Show page buttons in candidate window"), isOn: $selShowPageButtonsInCandidateUI LocalizedStringKey("Show page buttons in candidate window"),
).onChange( isOn: $selShowPageButtonsInCandidateUI.onChange {
of: selShowPageButtonsInCandidateUI, mgrPrefs.showPageButtonsInCandidateWindow = selShowPageButtonsInCandidateUI
perform: { value in
mgrPrefs.showPageButtonsInCandidateWindow = value
} }
) )
.controlSize(.small) .controlSize(.small)
@ -124,58 +131,59 @@ struct suiPrefPaneGeneral: View {
Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Output Settings:")) }) { Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Output Settings:")) }) {
Toggle( Toggle(
LocalizedStringKey("Auto-convert traditional Chinese glyphs to KangXi characters"), LocalizedStringKey("Auto-convert traditional Chinese glyphs to KangXi characters"),
isOn: $selEnableKanjiConvToKangXi isOn: $selEnableKanjiConvToKangXi.onChange {
).onChange(of: selEnableKanjiConvToKangXi) { value in mgrPrefs.chineseConversionEnabled = selEnableKanjiConvToKangXi
mgrPrefs.chineseConversionEnabled = value if selEnableKanjiConvToKangXi {
selEnableKanjiConvToKangXi = value mgrPrefs.shiftJISShinjitaiOutputEnabled = !selEnableKanjiConvToKangXi
if value { selEnableKanjiConvToJIS = !selEnableKanjiConvToKangXi
mgrPrefs.shiftJISShinjitaiOutputEnabled = !value
selEnableKanjiConvToJIS = !value
} }
} }
)
Toggle( Toggle(
LocalizedStringKey("Auto-convert traditional Chinese glyphs to JIS Shinjitai characters"), LocalizedStringKey("Auto-convert traditional Chinese glyphs to JIS Shinjitai characters"),
isOn: $selEnableKanjiConvToJIS isOn: $selEnableKanjiConvToJIS.onChange {
).onChange(of: selEnableKanjiConvToJIS) { value in mgrPrefs.shiftJISShinjitaiOutputEnabled = selEnableKanjiConvToJIS
mgrPrefs.shiftJISShinjitaiOutputEnabled = value if selEnableKanjiConvToJIS {
selEnableKanjiConvToJIS = value mgrPrefs.chineseConversionEnabled = !selEnableKanjiConvToJIS
if value { selEnableKanjiConvToKangXi = !selEnableKanjiConvToJIS
mgrPrefs.chineseConversionEnabled = !value
selEnableKanjiConvToKangXi = !value
} }
} }
)
Toggle( Toggle(
LocalizedStringKey("Show Hanyu-Pinyin in the inline composition buffer & tooltip"), LocalizedStringKey("Show Hanyu-Pinyin in the inline composition buffer & tooltip"),
isOn: $selShowHanyuPinyinInCompositionBuffer isOn: $selShowHanyuPinyinInCompositionBuffer.onChange {
).onChange(of: selShowHanyuPinyinInCompositionBuffer) { value in mgrPrefs.showHanyuPinyinInCompositionBuffer = selShowHanyuPinyinInCompositionBuffer
mgrPrefs.showHanyuPinyinInCompositionBuffer = value
selShowHanyuPinyinInCompositionBuffer = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"), LocalizedStringKey("Output Hanyu-Pinyin in lieu of Zhuyin when Ctrl(+Alt)+CMD+Enter"),
isOn: $selInlineDumpPinyinInLieuOfZhuyin isOn: $selInlineDumpPinyinInLieuOfZhuyin.onChange {
).onChange(of: selInlineDumpPinyinInLieuOfZhuyin) { value in mgrPrefs.inlineDumpPinyinInLieuOfZhuyin = selInlineDumpPinyinInLieuOfZhuyin
mgrPrefs.inlineDumpPinyinInLieuOfZhuyin = value
selInlineDumpPinyinInLieuOfZhuyin = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Stop farting (when typed phonetic combination is invalid, etc.)"), LocalizedStringKey("Stop farting (when typed phonetic combination is invalid, etc.)"),
isOn: $selEnableFartSuppressor isOn: $selEnableFartSuppressor.onChange {
).onChange(of: selEnableFartSuppressor) { value in mgrPrefs.shouldNotFartInLieuOfBeep = selEnableFartSuppressor
mgrPrefs.shouldNotFartInLieuOfBeep = value
clsSFX.beep() clsSFX.beep()
} }
)
} }
Preferences.Section(label: { Text(LocalizedStringKey("Misc Settings:")).controlSize(.small) }) { Preferences.Section(label: { Text(LocalizedStringKey("Misc Settings:")).controlSize(.small) }) {
Toggle(LocalizedStringKey("Check for updates automatically"), isOn: $selEnableAutoUpdateCheck) Toggle(
.onChange(of: selEnableAutoUpdateCheck) { value in LocalizedStringKey("Check for updates automatically"),
mgrPrefs.checkUpdateAutomatically = value isOn: $selEnableAutoUpdateCheck.onChange {
mgrPrefs.checkUpdateAutomatically = selEnableAutoUpdateCheck
} }
)
.controlSize(.small) .controlSize(.small)
Toggle(LocalizedStringKey("Debug Mode"), isOn: $selEnableDebugMode).controlSize(.small) Toggle(
.onChange(of: selEnableDebugMode) { value in LocalizedStringKey("Debug Mode"),
mgrPrefs.isDebugModeEnabled = value isOn: $selEnableDebugMode.onChange {
mgrPrefs.isDebugModeEnabled = selEnableDebugMode
} }
)
.controlSize(.small)
} }
} }
} }

View File

@ -8,8 +8,11 @@
import SwiftUI import SwiftUI
@available(macOS 11.0, *) @available(macOS 10.15, *)
struct suiPrefPaneKeyboard: View { struct suiPrefPaneKeyboard: View {
@State private var selSelectionKeysList = mgrPrefs.suggestedCandidateKeys
@State private var selSelectionKeys =
UserDefaults.standard.string(forKey: UserDef.kCandidateKeys.rawValue) ?? mgrPrefs.defaultCandidateKeys
@State private var selMandarinParser = UserDefaults.standard.integer(forKey: UserDef.kMandarinParser.rawValue) @State private var selMandarinParser = UserDefaults.standard.integer(forKey: UserDef.kMandarinParser.rawValue)
@State private var selBasicKeyboardLayout: String = @State private var selBasicKeyboardLayout: String =
UserDefaults.standard.string(forKey: UserDef.kBasicKeyboardLayout.rawValue) ?? mgrPrefs.basicKeyboardLayout UserDefaults.standard.string(forKey: UserDef.kBasicKeyboardLayout.rawValue) ?? mgrPrefs.basicKeyboardLayout
@ -40,9 +43,57 @@ struct suiPrefPaneKeyboard: View {
var body: some View { var body: some View {
Preferences.Container(contentWidth: contentWidth) { Preferences.Container(contentWidth: contentWidth) {
Preferences.Section(label: { Text(LocalizedStringKey("Selection Keys:")) }) {
ComboBox(
items: mgrPrefs.suggestedCandidateKeys,
text: $selSelectionKeys.onChange {
let value = selSelectionKeys
let keys: String = value.trimmingCharacters(in: .whitespacesAndNewlines).deduplicate
do {
try mgrPrefs.validate(candidateKeys: keys)
mgrPrefs.candidateKeys = keys
selSelectionKeys = mgrPrefs.candidateKeys
} catch mgrPrefs.CandidateKeyError.empty {
selSelectionKeys = mgrPrefs.candidateKeys
} catch {
if let window = ctlPrefUI.shared.controller.window {
let alert = NSAlert(error: error)
alert.beginSheetModal(for: window) { _ in
selSelectionKeys = mgrPrefs.candidateKeys
}
clsSFX.beep()
}
}
}
).frame(width: 180)
Text(
LocalizedStringKey(
"Choose or hit Enter to confim your prefered keys for selecting candidates."
)
)
.preferenceDescription()
}
Preferences.Section(label: { Text(LocalizedStringKey("Phonetic Parser:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("Phonetic Parser:")) }) {
HStack { HStack {
Picker("", selection: $selMandarinParser) { Picker(
"",
selection: $selMandarinParser.onChange {
let value = selMandarinParser
mgrPrefs.mandarinParser = value
switch value {
case 0:
if !AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ZhuyinBopomofo"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
default:
if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
}
}
) {
Group { Group {
Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0) Text(LocalizedStringKey("Dachen (Microsoft Standard / Wang / 01, etc.)")).tag(0)
Text(LocalizedStringKey("Eten Traditional")).tag(1) Text(LocalizedStringKey("Eten Traditional")).tag(1)
@ -66,20 +117,6 @@ struct suiPrefPaneKeyboard: View {
Text(LocalizedStringKey("Hualuo Pinyin with Numeral Intonation")).tag(13) Text(LocalizedStringKey("Hualuo Pinyin with Numeral Intonation")).tag(13)
Text(LocalizedStringKey("Universal Pinyin with Numeral Intonation")).tag(14) Text(LocalizedStringKey("Universal Pinyin with Numeral Intonation")).tag(14)
} }
}.onChange(of: selMandarinParser) { value in
mgrPrefs.mandarinParser = value
switch value {
case 0:
if !AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ZhuyinBopomofo"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
default:
if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(mgrPrefs.basicKeyboardLayout) {
mgrPrefs.basicKeyboardLayout = "com.apple.keylayout.ABC"
selBasicKeyboardLayout = mgrPrefs.basicKeyboardLayout
}
}
} }
.labelsHidden() .labelsHidden()
Button { Button {
@ -105,18 +142,22 @@ struct suiPrefPaneKeyboard: View {
} }
Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Basic Keyboard Layout:")) }) { Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Basic Keyboard Layout:")) }) {
HStack { HStack {
Picker("", selection: $selBasicKeyboardLayout) { Picker(
ForEach(0...(IME.arrEnumerateSystemKeyboardLayouts.count - 1), id: \.self) { id in "",
Text(IME.arrEnumerateSystemKeyboardLayouts[id].strName).tag( selection: $selBasicKeyboardLayout.onChange {
IME.arrEnumerateSystemKeyboardLayouts[id].strValue) let value = selBasicKeyboardLayout
}.id(UUID())
}.onChange(of: selBasicKeyboardLayout) { value in
mgrPrefs.basicKeyboardLayout = value mgrPrefs.basicKeyboardLayout = value
if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(value) { if AppleKeyboardConverter.arrDynamicBasicKeyLayout.contains(value) {
mgrPrefs.mandarinParser = 0 mgrPrefs.mandarinParser = 0
selMandarinParser = mgrPrefs.mandarinParser selMandarinParser = mgrPrefs.mandarinParser
} }
} }
) {
ForEach(0...(IME.arrEnumerateSystemKeyboardLayouts.count - 1), id: \.self) { id in
Text(IME.arrEnumerateSystemKeyboardLayouts[id].strName).tag(
IME.arrEnumerateSystemKeyboardLayouts[id].strValue)
}.id(UUID())
}
.labelsHidden() .labelsHidden()
.frame(width: 240.0) .frame(width: 240.0)
} }
@ -126,53 +167,46 @@ struct suiPrefPaneKeyboard: View {
Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Keyboard Shortcuts:")) }) { Preferences.Section(bottomDivider: true, label: { Text(LocalizedStringKey("Keyboard Shortcuts:")) }) {
Toggle( Toggle(
LocalizedStringKey("Per-Char Select Mode"), LocalizedStringKey("Per-Char Select Mode"),
isOn: $selUsingHotKeySCPC isOn: $selUsingHotKeySCPC.onChange {
).onChange(of: selUsingHotKeySCPC) { value in mgrPrefs.usingHotKeySCPC = selUsingHotKeySCPC
mgrPrefs.usingHotKeySCPC = value
selUsingHotKeySCPC = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Per-Char Associated Phrases"), LocalizedStringKey("Per-Char Associated Phrases"),
isOn: $selUsingHotKeyAssociates isOn: $selUsingHotKeyAssociates.onChange {
).onChange(of: selUsingHotKeyAssociates) { value in mgrPrefs.usingHotKeyAssociates = selUsingHotKeyAssociates
mgrPrefs.usingHotKeyAssociates = value
selUsingHotKeyAssociates = value
} }
)
Toggle( Toggle(
LocalizedStringKey("CNS11643 Mode"), LocalizedStringKey("CNS11643 Mode"),
isOn: $selUsingHotKeyCNS isOn: $selUsingHotKeyCNS.onChange {
).onChange(of: selUsingHotKeyCNS) { value in mgrPrefs.usingHotKeyCNS = selUsingHotKeyCNS
mgrPrefs.usingHotKeyCNS = value
selUsingHotKeyCNS = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Force KangXi Writing"), LocalizedStringKey("Force KangXi Writing"),
isOn: $selUsingHotKeyKangXi isOn: $selUsingHotKeyKangXi.onChange {
).onChange(of: selUsingHotKeyKangXi) { value in mgrPrefs.usingHotKeyKangXi = selUsingHotKeyKangXi
mgrPrefs.usingHotKeyKangXi = value
selUsingHotKeyKangXi = value
} }
)
Toggle( Toggle(
LocalizedStringKey("JIS Shinjitai Output"), LocalizedStringKey("JIS Shinjitai Output"),
isOn: $selUsingHotKeyJIS isOn: $selUsingHotKeyJIS.onChange {
).onChange(of: selUsingHotKeyJIS) { value in mgrPrefs.usingHotKeyJIS = selUsingHotKeyJIS
mgrPrefs.usingHotKeyJIS = value
selUsingHotKeyJIS = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Half-Width Punctuation Mode"), LocalizedStringKey("Half-Width Punctuation Mode"),
isOn: $selUsingHotKeyHalfWidthASCII isOn: $selUsingHotKeyHalfWidthASCII.onChange {
).onChange(of: selUsingHotKeyHalfWidthASCII) { value in mgrPrefs.usingHotKeyHalfWidthASCII = selUsingHotKeyHalfWidthASCII
mgrPrefs.usingHotKeyHalfWidthASCII = value
selUsingHotKeyHalfWidthASCII = value
} }
)
Toggle( Toggle(
LocalizedStringKey("Currency Numeral Output"), LocalizedStringKey("Currency Numeral Output"),
isOn: $selUsingHotKeyCurrencyNumerals isOn: $selUsingHotKeyCurrencyNumerals.onChange {
).onChange(of: selUsingHotKeyCurrencyNumerals) { value in mgrPrefs.usingHotKeyCurrencyNumerals = selUsingHotKeyCurrencyNumerals
mgrPrefs.usingHotKeyCurrencyNumerals = value
selUsingHotKeyCurrencyNumerals = value
} }
)
} }
} }
Divider() Divider()
@ -181,7 +215,7 @@ struct suiPrefPaneKeyboard: View {
VStack(alignment: .leading, spacing: 10) { VStack(alignment: .leading, spacing: 10) {
Text( Text(
LocalizedStringKey( LocalizedStringKey(
"Non-QWERTY alphanumeral keyboard layouts are for Hanyu Pinyin parser only." "Non-QWERTY alphanumerical keyboard layouts are for Hanyu Pinyin parser only."
) )
) )
.preferenceDescription() .preferenceDescription()

View File

@ -375,7 +375,7 @@ extension ctlPrefWindow: NSToolbarDelegate {
systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences" systemSymbolName: "wrench.and.screwdriver.fill", accessibilityDescription: "General Preferences"
) )
} else { } else {
item.image = NSImage(named: NSImage.homeTemplateName) item.image = NSImage(named: "PrefToolbar-General")
} }
item.action = #selector(showGeneralView(_:)) item.action = #selector(showGeneralView(_:))
@ -387,7 +387,7 @@ extension ctlPrefWindow: NSToolbarDelegate {
systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences" systemSymbolName: "person.fill.questionmark", accessibilityDescription: "Experiences Preferences"
) )
} else { } else {
item.image = NSImage(named: NSImage.flowViewTemplateName) item.image = NSImage(named: "PrefToolbar-Experiences")
} }
item.action = #selector(showExperienceView(_:)) item.action = #selector(showExperienceView(_:))
@ -399,7 +399,7 @@ extension ctlPrefWindow: NSToolbarDelegate {
systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences" systemSymbolName: "character.book.closed.fill", accessibilityDescription: "Dictionary Preferences"
) )
} else { } else {
item.image = NSImage(named: NSImage.bookmarksTemplateName) item.image = NSImage(named: "PrefToolbar-Dictionary")
} }
item.action = #selector(showDictionaryView(_:)) item.action = #selector(showDictionaryView(_:))
@ -409,7 +409,7 @@ extension ctlPrefWindow: NSToolbarDelegate {
if #available(macOS 11.0, *) { if #available(macOS 11.0, *) {
item.image = NSImage(systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences") item.image = NSImage(systemSymbolName: "keyboard.macwindow", accessibilityDescription: "Keyboard Preferences")
} else { } else {
item.image = NSImage(named: NSImage.slideshowTemplateName) item.image = NSImage(named: "PrefToolbar-Keyboard")
} }
item.action = #selector(showKeyboardView(_:)) item.action = #selector(showKeyboardView(_:))

View File

@ -410,7 +410,7 @@
</column> </column>
</cells> </cells>
<connections> <connections>
<binding destination="32" name="selectedTag" keyPath="values.SelectPhraseAfterCursorAsCandidate" id="104"/> <binding destination="32" name="selectedTag" keyPath="values.UseRearCursorMode" id="8rm-vc-0Db"/>
</connections> </connections>
</matrix> </matrix>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7z2-DD-c58"> <button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7z2-DD-c58">

View File

@ -3,9 +3,9 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.9.0</string> <string>1.9.1</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1990</string> <string>1991</string>
<key>UpdateInfoEndpoint</key> <key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string> <string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key> <key>UpdateInfoSite</key>

View File

@ -726,7 +726,7 @@
<key>USE_HFS+_COMPRESSION</key> <key>USE_HFS+_COMPRESSION</key>
<false/> <false/>
<key>VERSION</key> <key>VERSION</key>
<string>1.9.0</string> <string>1.9.1</string>
</dict> </dict>
<key>TYPE</key> <key>TYPE</key>
<integer>0</integer> <integer>0</integer>

View File

@ -117,6 +117,7 @@
5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2528840E6200DBD48E /* template-replacements.txt */; }; 5BF9DA2A28840E6200DBD48E /* template-replacements.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2528840E6200DBD48E /* template-replacements.txt */; };
5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */; }; 5BF9DA2B28840E6200DBD48E /* template-userphrases.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */; };
5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */; }; 5BF9DA2D288427E000DBD48E /* template-associatedPhrases-cht.txt in Resources */ = {isa = PBXBuildFile; fileRef = 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */; };
5BF9EC1628A2BFC600333639 /* lmPlainBopomofo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BF9EC1528A2BFC600333639 /* lmPlainBopomofo.swift */; };
5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */; }; 5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */; };
6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; }; 6A187E2616004C5900466B2E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6A187E2816004C5900466B2E /* MainMenu.xib */; };
6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; }; 6A225A1F23679F2600F685C6 /* NotarizedArchives in Resources */ = {isa = PBXBuildFile; fileRef = 6A225A1E23679F2600F685C6 /* NotarizedArchives */; };
@ -333,6 +334,7 @@
5BF9DA2528840E6200DBD48E /* template-replacements.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-replacements.txt"; sourceTree = "<group>"; usesTabs = 0; }; 5BF9DA2528840E6200DBD48E /* template-replacements.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-replacements.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2628840E6200DBD48E /* template-userphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-userphrases.txt"; sourceTree = "<group>"; usesTabs = 0; }; 5BF9DA2628840E6200DBD48E /* template-userphrases.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; path = "template-userphrases.txt"; sourceTree = "<group>"; usesTabs = 0; };
5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-cht.txt"; path = "../Data/components/cht/template-associatedPhrases-cht.txt"; sourceTree = "<group>"; }; 5BF9DA2C2884247800DBD48E /* template-associatedPhrases-cht.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; lineEnding = 0; name = "template-associatedPhrases-cht.txt"; path = "../Data/components/cht/template-associatedPhrases-cht.txt"; sourceTree = "<group>"; };
5BF9EC1528A2BFC600333639 /* lmPlainBopomofo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = lmPlainBopomofo.swift; sourceTree = "<group>"; };
5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlCandidateIMK.swift; sourceTree = "<group>"; }; 5BFDF010289635C100417BBC /* ctlCandidateIMK.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlCandidateIMK.swift; sourceTree = "<group>"; };
5BFDF48C27B51867009523B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; }; 5BFDF48C27B51867009523B6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Main.strings"; sourceTree = "<group>"; };
6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewing.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewing.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -432,6 +434,7 @@
5B407309281672610023DFFF /* lmAssociates.swift */, 5B407309281672610023DFFF /* lmAssociates.swift */,
5B887F2F2826AEA400B6651E /* lmCoreEX.swift */, 5B887F2F2826AEA400B6651E /* lmCoreEX.swift */,
5B54E742283A7D89001ECBDC /* lmCoreNS.swift */, 5B54E742283A7D89001ECBDC /* lmCoreNS.swift */,
5BF9EC1528A2BFC600333639 /* lmPlainBopomofo.swift */,
5B40730A281672610023DFFF /* lmReplacements.swift */, 5B40730A281672610023DFFF /* lmReplacements.swift */,
5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */, 5BA0DF2E2817857D009E73BB /* lmUserOverride.swift */,
); );
@ -1177,6 +1180,7 @@
5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */, 5BA9FD1027FEDB6B002DE248 /* suiPrefPaneKeyboard.swift in Sources */,
5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */, 5B3133BF280B229700A4A505 /* KeyHandler_States.swift in Sources */,
5B2170E1289FACAD00BE7304 /* 0_Megrez.swift in Sources */, 5B2170E1289FACAD00BE7304 /* 0_Megrez.swift in Sources */,
5BF9EC1628A2BFC600333639 /* lmPlainBopomofo.swift in Sources */,
5B3A87BC28597CDB0090E163 /* LMSymbolNode.swift in Sources */, 5B3A87BC28597CDB0090E163 /* LMSymbolNode.swift in Sources */,
5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */, 5BA9FD4327FEF3C8002DE248 /* Preferences.swift in Sources */,
5BA9FD4427FEF3C8002DE248 /* SegmentedControlStyleViewController.swift in Sources */, 5BA9FD4427FEF3C8002DE248 /* SegmentedControlStyleViewController.swift in Sources */,
@ -1409,7 +1413,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
@ -1419,7 +1423,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1448,13 +1452,13 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewingTests;
@ -1485,7 +1489,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
@ -1506,7 +1510,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1535,7 +1539,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1552,7 +1556,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES; MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingPhraseEditor;
@ -1666,7 +1670,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1694,7 +1698,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1721,7 +1725,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1743,7 +1747,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.inputmethod.vChewing;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -1765,7 +1769,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1785,7 +1789,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1807,7 +1811,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1990; CURRENT_PROJECT_VERSION = 1991;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
@ -1821,7 +1825,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 1.9.0; MARKETING_VERSION = 1.9.1;
PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_BUNDLE_IDENTIFIER = "org.atelierInmu.vChewing.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";