PrefUI // Catalina compatibility.

This commit is contained in:
ShikiSuen 2022-08-11 11:32:24 +08:00
parent 43db1cb7e5
commit ef7bce4321
6 changed files with 308 additions and 230 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]

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,9 +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 selCursorPosition = @State private var selCursorPosition =
UserDefaults.standard.bool( UserDefaults.standard.bool(
forKey: UserDef.kUseRearCursorMode.rawValue) ? 1 : 0 forKey: UserDef.kUseRearCursorMode.rawValue) ? 1 : 0
@ -53,11 +52,14 @@ struct suiPrefPaneExperience: View {
var body: some View { var body: some View {
Preferences.Container(contentWidth: contentWidth) { Preferences.Container(contentWidth: contentWidth) {
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())
@ -65,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()
@ -84,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())
@ -96,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())
@ -111,39 +122,40 @@ 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("Emulating select-candidate-per-character mode"),
).onChange(of: selEnableSCPCTypingMode) { value in isOn: $selEnableSCPCTypingMode.onChange {
mgrPrefs.useSCPCTypingMode = value 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,7 +8,7 @@
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 selSelectionKeysList = mgrPrefs.suggestedCandidateKeys
@State private var selSelectionKeys = @State private var selSelectionKeys =
@ -44,9 +44,10 @@ 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:")) }) { Preferences.Section(label: { Text(LocalizedStringKey("Selection Keys:")) }) {
ComboBox(items: mgrPrefs.suggestedCandidateKeys, text: $selSelectionKeys).frame(width: 180).onChange( ComboBox(
of: selSelectionKeys items: mgrPrefs.suggestedCandidateKeys,
) { value in text: $selSelectionKeys.onChange {
let value = selSelectionKeys
let keys: String = value.trimmingCharacters(in: .whitespacesAndNewlines).deduplicate let keys: String = value.trimmingCharacters(in: .whitespacesAndNewlines).deduplicate
do { do {
try mgrPrefs.validate(candidateKeys: keys) try mgrPrefs.validate(candidateKeys: keys)
@ -64,6 +65,7 @@ struct suiPrefPaneKeyboard: View {
} }
} }
} }
).frame(width: 180)
Text( Text(
LocalizedStringKey( LocalizedStringKey(
"Choose or hit Enter to confim your prefered keys for selecting candidates." "Choose or hit Enter to confim your prefered keys for selecting candidates."
@ -73,7 +75,25 @@ struct suiPrefPaneKeyboard: View {
} }
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)
@ -97,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 {
@ -136,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)
} }
@ -157,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()