From 36e9a0c1dd373ad447566e3a6e623a9171820ff9 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 7 Dec 2022 20:22:34 +0800 Subject: [PATCH] PrefWindow // Implementing PhraseEditorCocoa. --- .../WindowControllers/CtlPrefWindow.swift | 38 ++- .../CtlPrefWindow_PhraseEditor.swift | 255 ++++++++++++++++ .../Resources/Base.lproj/Localizable.strings | 1 + Source/Resources/en.lproj/Localizable.strings | 1 + Source/Resources/ja.lproj/Localizable.strings | 1 + .../zh-Hans.lproj/Localizable.strings | 1 + .../zh-Hant.lproj/Localizable.strings | 1 + .../WindowNIBs/Base.lproj/frmAboutWindow.xib | 4 +- .../WindowNIBs/Base.lproj/frmPrefWindow.xib | 286 ++++++++++++++++++ .../WindowNIBs/en.lproj/frmPrefWindow.strings | 1 + .../WindowNIBs/ja.lproj/frmPrefWindow.strings | 1 + .../zh-Hans.lproj/frmPrefWindow.strings | 1 + .../zh-Hant.lproj/frmPrefWindow.strings | 1 + vChewing.xcodeproj/project.pbxproj | 4 + 14 files changed, 593 insertions(+), 3 deletions(-) create mode 100644 Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift diff --git a/Source/Modules/WindowControllers/CtlPrefWindow.swift b/Source/Modules/WindowControllers/CtlPrefWindow.swift index b010aaad..9817a613 100644 --- a/Source/Modules/WindowControllers/CtlPrefWindow.swift +++ b/Source/Modules/WindowControllers/CtlPrefWindow.swift @@ -18,6 +18,7 @@ extension NSToolbarItem.Identifier { fileprivate static let ofGeneral = NSToolbarItem.Identifier(rawValue: "tabGeneral") fileprivate static let ofExperience = NSToolbarItem.Identifier(rawValue: "tabExperience") fileprivate static let ofDictionary = NSToolbarItem.Identifier(rawValue: "tabDictionary") + fileprivate static let ofPhrases = NSToolbarItem.Identifier(rawValue: "tabPhrases") fileprivate static let ofCassette = NSToolbarItem.Identifier(rawValue: "tabCassette") fileprivate static let ofKeyboard = NSToolbarItem.Identifier(rawValue: "tabKeyboard") fileprivate static let ofDevZone = NSToolbarItem.Identifier(rawValue: "tabDevZone") @@ -38,9 +39,30 @@ class CtlPrefWindow: NSWindowController { @IBOutlet var tglControlDevZoneIMKCandidate: NSButton! @IBOutlet var cmbCandidateFontSize: NSPopUpButton! + @IBOutlet var cmbPEInputModeMenu: NSPopUpButton! + @IBOutlet var cmbPEDataTypeMenu: NSPopUpButton! + @IBOutlet var btnPEReload: NSButton! + @IBOutlet var btnPEConsolidate: NSButton! + @IBOutlet var btnPESave: NSButton! + @IBOutlet var btnPEAdd: NSButton! + @IBOutlet var btnPEOpenExternally: NSButton! + @IBOutlet var tfdPETextEditor: NSTextView! + @IBOutlet var txtPECommentField: NSTextField! + @IBOutlet var txtPEField1: NSTextField! + @IBOutlet var txtPEField2: NSTextField! + @IBOutlet var txtPEField3: NSTextField! + var isLoading = false { + didSet { setPEUIControlAvailability() } + } + + var isSaved = false { + didSet { setPEUIControlAvailability() } + } + @IBOutlet var vwrGeneral: NSView! @IBOutlet var vwrExperience: NSView! @IBOutlet var vwrDictionary: NSView! + @IBOutlet var vwrPhrases: NSView! @IBOutlet var vwrCassette: NSView! @IBOutlet var vwrKeyboard: NSView! @IBOutlet var vwrDevZone: NSView! @@ -152,6 +174,8 @@ class CtlPrefWindow: NSWindowController { if PrefMgr.shared.useIMKCandidateWindow { selectionKeyComboBox.isEnabled = false // 無法與 IMKCandidates 協作,故禁用。 } + + initPhraseEditor() } // 這裡有必要加上這段處理,用來確保藉由偏好設定介面動過的 CNS 開關能夠立刻生效。 @@ -343,6 +367,8 @@ class CtlPrefWindow: NSWindowController { } } +// MARK: - NSToolbarDelegate Methods + extension CtlPrefWindow: NSToolbarDelegate { func use(view: NSView) { guard let window = window else { @@ -360,7 +386,7 @@ extension CtlPrefWindow: NSToolbarDelegate { } var toolbarIdentifiers: [NSToolbarItem.Identifier] { - [.ofGeneral, .ofExperience, .ofDictionary, .ofCassette, .ofKeyboard] + [.ofGeneral, .ofExperience, .ofDictionary, .ofPhrases, .ofCassette, .ofKeyboard] } func toolbarDefaultItemIdentifiers(_: NSToolbar) -> [NSToolbarItem.Identifier] { @@ -390,6 +416,11 @@ extension CtlPrefWindow: NSToolbarDelegate { window?.toolbar?.selectedItemIdentifier = .ofDictionary } + @objc func showPhrasesView(_: Any?) { + use(view: vwrPhrases) + window?.toolbar?.selectedItemIdentifier = .ofPhrases + } + @objc func showCassetteView(_: Any?) { use(view: vwrCassette) window?.toolbar?.selectedItemIdentifier = .ofCassette @@ -430,6 +461,11 @@ extension CtlPrefWindow: NSToolbarDelegate { item.image = .tabImageDictionary item.action = #selector(showDictionaryView(_:)) + case .ofPhrases: + item.label = CtlPrefWindow.locPhrasesTabTitle + item.image = .tabImagePhrases + item.action = #selector(showPhrasesView(_:)) + case .ofCassette: let title = NSLocalizedString("Cassette", comment: "") item.label = title diff --git a/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift new file mode 100644 index 00000000..bd669d89 --- /dev/null +++ b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift @@ -0,0 +1,255 @@ +// (c) 2011 and onwards The OpenVanilla Project (MIT License). +// All possible vChewing-specific modifications are of: +// (c) 2021 and onwards The vChewing Project (MIT-NTL License). +// ==================== +// This code is released under the MIT license (SPDX-License-Identifier: MIT) +// ... with NTL restriction stating that: +// No trademark license is granted to use the trade names, trademarks, service +// marks, or product names of Contributor, except as required to fulfill notice +// requirements defined in MIT License. + +import Foundation +import LangModelAssembly +import PhraseEditorUI +import Shared + +extension CtlPrefWindow: NSTextViewDelegate, NSTextFieldDelegate { + var selInputMode: Shared.InputMode { + switch cmbPEInputModeMenu.selectedTag() { + case 0: return .imeModeCHS + case 1: return .imeModeCHT + default: return .imeModeNULL + } + } + + var selUserDataType: vChewingLM.ReplacableUserDataType { + switch cmbPEDataTypeMenu.selectedTag() { + case 0: return .thePhrases + case 1: return .theFilter + case 2: return .theReplacements + case 3: return .theAssociates + case 4: return .theSymbols + default: return .thePhrases + } + } + + func updatePhraseEditor() { + updateLabels() + clearAllFields() + isLoading = true + tfdPETextEditor.string = NSLocalizedString("Loading…", comment: "") + DispatchQueue.main.async { [self] in + tfdPETextEditor.string = LMMgr.retrieveData(mode: selInputMode, type: selUserDataType) + isSaved = true + isLoading = false + } + } + + func setPEUIControlAvailability() { + btnPEReload.isEnabled = selInputMode != .imeModeNULL && !isLoading + btnPEConsolidate.isEnabled = selInputMode != .imeModeNULL && !isLoading + btnPESave.isEnabled = true // 暫時沒辦法捕捉到 TextView 的內容變更事件,故作罷。 + btnPEAdd.isEnabled = + !txtPEField1.isEmpty && !txtPEField2.isEmpty && selInputMode != .imeModeNULL && !isLoading + tfdPETextEditor.isEditable = selInputMode != .imeModeNULL && !isLoading + txtPEField1.isEnabled = selInputMode != .imeModeNULL && !isLoading + txtPEField2.isEnabled = selInputMode != .imeModeNULL && !isLoading + txtPEField3.isEnabled = selInputMode != .imeModeNULL && !isLoading + txtPEField3.isHidden = selUserDataType != .thePhrases || isLoading + txtPECommentField.isEnabled = selUserDataType != .theAssociates && !isLoading + } + + func updateLabels() { + clearAllFields() + switch selUserDataType { + case .thePhrases: + txtPEField1.placeholderString = UITerms.AddPhrases.locPhrase.localized.0 + txtPEField2.placeholderString = UITerms.AddPhrases.locReadingOrStroke.localized.0 + txtPEField3.placeholderString = UITerms.AddPhrases.locWeight.localized.0 + txtPECommentField.placeholderString = UITerms.AddPhrases.locComment.localized.0 + case .theFilter: + txtPEField1.placeholderString = UITerms.AddPhrases.locPhrase.localized.0 + txtPEField2.placeholderString = UITerms.AddPhrases.locReadingOrStroke.localized.0 + txtPEField3.placeholderString = "" + txtPECommentField.placeholderString = UITerms.AddPhrases.locComment.localized.0 + case .theReplacements: + txtPEField1.placeholderString = UITerms.AddPhrases.locReplaceTo.localized.0 + txtPEField2.placeholderString = UITerms.AddPhrases.locReplaceTo.localized.1 + txtPEField3.placeholderString = "" + txtPECommentField.placeholderString = UITerms.AddPhrases.locComment.localized.0 + case .theAssociates: + txtPEField1.placeholderString = UITerms.AddPhrases.locInitial.localized.0 + txtPEField2.placeholderString = { + let result = UITerms.AddPhrases.locPhrase.localized.0 + return (result == "Phrase") ? "Phrases" : result + }() + txtPEField3.placeholderString = "" + txtPECommentField.placeholderString = NSLocalizedString( + "Inline comments are not supported in associated phrases.", comment: "" + ) + case .theSymbols: + txtPEField1.placeholderString = UITerms.AddPhrases.locPhrase.localized.0 + txtPEField2.placeholderString = UITerms.AddPhrases.locReadingOrStroke.localized.0 + txtPEField3.placeholderString = "" + txtPECommentField.placeholderString = UITerms.AddPhrases.locComment.localized.0 + } + } + + func clearAllFields() { + txtPEField1.stringValue = "" + txtPEField2.stringValue = "" + txtPEField3.stringValue = "" + txtPECommentField.stringValue = "" + } + + func initPhraseEditor() { + // InputMode combobox. + cmbPEInputModeMenu.menu?.removeAllItems() + let menuItemCHS = NSMenuItem() + menuItemCHS.title = NSLocalizedString("Simplified Chinese", comment: "") + menuItemCHS.tag = 0 + let menuItemCHT = NSMenuItem() + menuItemCHT.title = NSLocalizedString("Traditional Chinese", comment: "") + menuItemCHT.tag = 1 + cmbPEInputModeMenu.menu?.addItem(menuItemCHS) + cmbPEInputModeMenu.menu?.addItem(menuItemCHT) + switch IMEApp.currentInputMode { + case .imeModeCHS: cmbPEInputModeMenu.select(menuItemCHS) + case .imeModeCHT: cmbPEInputModeMenu.select(menuItemCHT) + case .imeModeNULL: cmbPEInputModeMenu.select(menuItemCHT) + } + + // DataType combobox. + cmbPEDataTypeMenu.menu?.removeAllItems() + var defaultDataTypeMenuItem: NSMenuItem? + for (i, neta) in vChewingLM.ReplacableUserDataType.allCases.enumerated() { + let newMenuItem = NSMenuItem() + newMenuItem.title = neta.localizedDescription + newMenuItem.tag = i + cmbPEDataTypeMenu.menu?.addItem(newMenuItem) + if i == 0 { defaultDataTypeMenuItem = newMenuItem } + } + guard let defaultDataTypeMenuItem = defaultDataTypeMenuItem else { return } + cmbPEDataTypeMenu.select(defaultDataTypeMenuItem) + + // Buttons. + btnPEReload.title = NSLocalizedString("Reload", comment: "") + btnPEConsolidate.title = NSLocalizedString("Consolidate", comment: "") + btnPESave.title = NSLocalizedString("Save", comment: "") + btnPEAdd.title = UITerms.AddPhrases.locAdd.localized.0 + btnPEOpenExternally.title = NSLocalizedString("...", comment: "") + + // Text Editor View + tfdPETextEditor.font = NSFont.systemFont(ofSize: 13, weight: .regular) + + // Tab key targets. + tfdPETextEditor.delegate = self + txtPECommentField.nextKeyView = txtPEField1 + txtPEField1.nextKeyView = txtPEField2 + txtPEField2.nextKeyView = txtPEField3 + txtPEField3.nextKeyView = btnPEAdd + + // Delegates. + tfdPETextEditor.delegate = self + txtPECommentField.delegate = self + txtPEField1.delegate = self + txtPEField2.delegate = self + txtPEField3.delegate = self + + // Finally, update the entire editor UI. + updatePhraseEditor() + } + + func controlTextDidChange(_: Notification) { setPEUIControlAvailability() } + + @IBAction func inputModePEMenuDidChange(_: NSPopUpButton) { updatePhraseEditor() } + + @IBAction func dataTypePEMenuDidChange(_: NSPopUpButton) { updatePhraseEditor() } + + @IBAction func reloadPEButtonClicked(_: NSButton) { updatePhraseEditor() } + + @IBAction func consolidatePEButtonClicked(_: NSButton) { + DispatchQueue.main.async { [self] in + isLoading = true + vChewingLM.LMConsolidator.consolidate(text: &tfdPETextEditor.string, pragma: false) + isLoading = false + isSaved = false + } + } + + @IBAction func savePEButtonClicked(_: NSButton) { + // guard !isSaved else { return } + let toSave = tfdPETextEditor.string + isLoading = true + tfdPETextEditor.string = NSLocalizedString("Loading…", comment: "") + let newResult = LMMgr.saveData(mode: selInputMode, type: selUserDataType, data: toSave) + tfdPETextEditor.string = newResult + isLoading = false + isSaved = true + } + + @IBAction func openExternallyPEButtonClicked(_: NSButton) { + DispatchQueue.main.async { [self] in + LMMgr.shared.openPhraseFile(mode: selInputMode, type: selUserDataType, app: "Finder") + } + } + + @IBAction func addPEButtonClicked(_: NSButton) { + DispatchQueue.main.async { [self] in + txtPEField1.stringValue.removeAll { "  \t\n\r".contains($0) } + if selUserDataType != .theAssociates { + txtPEField2.stringValue.regReplace(pattern: #"( +| +| +|\t+)+"#, replaceWith: "-") + } + txtPEField2.stringValue.removeAll { + selUserDataType == .theAssociates ? "\n\r".contains($0) : "  \t\n\r".contains($0) + } + txtPEField3.stringValue.removeAll { !"0123456789.-".contains($0) } + txtPECommentField.stringValue.removeAll { "\n\r".contains($0) } + guard !txtPEField1.stringValue.isEmpty, !txtPEField2.stringValue.isEmpty else { return } + var arrResult: [String] = [txtPEField1.stringValue, txtPEField2.stringValue] + if let weightVal = Double(txtPEField3.stringValue), weightVal < 0 { + arrResult.append(weightVal.description) + } + if !txtPECommentField.stringValue.isEmpty { arrResult.append("#" + txtPECommentField.stringValue) } + if LMMgr.checkIfUserPhraseExist( + userPhrase: txtPEField1.stringValue, mode: selInputMode, key: txtPEField2.stringValue + ) { + arrResult.append("\t#𝙾𝚟𝚎𝚛𝚛𝚒𝚍𝚎") + } + if let lastChar = tfdPETextEditor.string.last, !"\n".contains(lastChar) { + arrResult.insert("\n", at: 0) + } + tfdPETextEditor.string.append(arrResult.joined(separator: " ") + "\n") + isSaved = false + clearAllFields() + } + } +} + +private enum UITerms { + fileprivate enum AddPhrases: String { + case locPhrase = "Phrase" + case locReadingOrStroke = "Reading/Stroke" + case locWeight = "Weight" + case locComment = "Comment" + case locReplaceTo = "Replace to" + case locAdd = "Add" + case locInitial = "Initial" + + var localized: (String, String) { + if self == .locAdd { + let loc = PrefMgr.shared.appleLanguages[0] + return loc.contains("zh") ? ("添入", "") : loc.contains("ja") ? ("記入", "") : ("Add", "") + } + let rawArray = NSLocalizedString(self.rawValue, comment: "").components(separatedBy: " ") + if rawArray.isEmpty { return ("N/A", "N/A") } + let val1: String = rawArray[0] + let val2: String = (rawArray.count >= 2) ? rawArray[1] : "" + return (val1, val2) + } + } +} + +extension NSTextField { + fileprivate var isEmpty: Bool { stringValue.isEmpty } +} diff --git a/Source/Resources/Base.lproj/Localizable.strings b/Source/Resources/Base.lproj/Localizable.strings index 5d4e8851..30467147 100644 --- a/Source/Resources/Base.lproj/Localizable.strings +++ b/Source/Resources/Base.lproj/Localizable.strings @@ -92,6 +92,7 @@ "⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ Phrase replacement mode enabled, interfering user phrase entry."; "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match."; "Per-Char Select Mode" = "Per-Char Select Mode"; +"Inline comments are not supported in associated phrases." = "Inline comments are not supported in associated phrases."; "CNS11643 Mode" = "CNS11643 Mode"; "JIS Shinjitai Output" = "JIS Shinjitai Output"; "Per-Char Associated Phrases" = "Per-Char Associated Phrases"; diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 5d4e8851..30467147 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -92,6 +92,7 @@ "⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ Phrase replacement mode enabled, interfering user phrase entry."; "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match."; "Per-Char Select Mode" = "Per-Char Select Mode"; +"Inline comments are not supported in associated phrases." = "Inline comments are not supported in associated phrases."; "CNS11643 Mode" = "CNS11643 Mode"; "JIS Shinjitai Output" = "JIS Shinjitai Output"; "Per-Char Associated Phrases" = "Per-Char Associated Phrases"; diff --git a/Source/Resources/ja.lproj/Localizable.strings b/Source/Resources/ja.lproj/Localizable.strings index fa745e46..ccb7b633 100644 --- a/Source/Resources/ja.lproj/Localizable.strings +++ b/Source/Resources/ja.lproj/Localizable.strings @@ -92,6 +92,7 @@ "⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 言葉置換機能稼働中、新添付言葉にも影響。"; "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 対処不可:緩衝列の字数は読みの数と不同等。"; "Per-Char Select Mode" = "全候補入力モード"; +"Inline comments are not supported in associated phrases." = "インラインメモは連想語彙辞書で使えません。"; "CNS11643 Mode" = "全字庫モード"; "JIS Shinjitai Output" = "JIS 新字体モード"; "Per-Char Associated Phrases" = "全候補入力で連想語彙"; diff --git a/Source/Resources/zh-Hans.lproj/Localizable.strings b/Source/Resources/zh-Hans.lproj/Localizable.strings index f0962e14..4a37e1e6 100644 --- a/Source/Resources/zh-Hans.lproj/Localizable.strings +++ b/Source/Resources/zh-Hans.lproj/Localizable.strings @@ -92,6 +92,7 @@ "⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 语汇置换功能已启用,会波及语汇自订。"; "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 无法处理:组字区字数与读音数不对应。"; "Per-Char Select Mode" = "模拟逐字选字输入"; +"Inline comments are not supported in associated phrases." = "联想词不支援行内注解。"; "CNS11643 Mode" = "全字库模式"; "JIS Shinjitai Output" = "JIS 新字体模式"; "Per-Char Associated Phrases" = "逐字选字联想模式"; diff --git a/Source/Resources/zh-Hant.lproj/Localizable.strings b/Source/Resources/zh-Hant.lproj/Localizable.strings index 6ccd5020..49372efa 100644 --- a/Source/Resources/zh-Hant.lproj/Localizable.strings +++ b/Source/Resources/zh-Hant.lproj/Localizable.strings @@ -92,6 +92,7 @@ "⚠︎ Phrase replacement mode enabled, interfering user phrase entry." = "⚠︎ 語彙置換功能已啟用,會波及語彙自訂。"; "⚠︎ Unhandlable: Chars and Readings in buffer doesn't match." = "⚠︎ 無法處理:組字區字數與讀音數不對應。"; "Per-Char Select Mode" = "模擬逐字選字輸入"; +"Inline comments are not supported in associated phrases." = "聯想詞不支援行內註解。"; "CNS11643 Mode" = "全字庫模式"; "JIS Shinjitai Output" = "JIS 新字體模式"; "Per-Char Associated Phrases" = "逐字選字聯想模式"; diff --git a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib index 226aa0f9..81d89a1b 100644 --- a/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmAboutWindow.xib @@ -1,8 +1,8 @@ - + - + diff --git a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib index bbe85547..19e96a0c 100644 --- a/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib +++ b/Source/WindowNIBs/Base.lproj/frmPrefWindow.xib @@ -1,6 +1,7 @@ + @@ -8,12 +9,24 @@ + + + + + + + + + + + + @@ -21,6 +34,7 @@ + @@ -1673,5 +1687,277 @@ Features listed here may not work as expected. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings index 470f3cac..a13e3f1c 100644 --- a/Source/WindowNIBs/en.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/en.lproj/frmPrefWindow.strings @@ -115,6 +115,7 @@ "wN3-k3-b2a.title" = "Choose your desired user data folder path. Will be omitted if invalid."; "wQ9-px-b07.title" = "Basic keyboard layout option will only affect the appearance of the on-screen-keyboard if the current Mandarin parser is not (any) pinyin."; "Wvt-HE-LOv.title" = "Keyboard Layout"; +"WX6-BW-JPM.title" = "This editor only: Auto-reload modifications happened outside of this editor"; "xC5-yV-1W1.title" = "Choose your preferred layout of the candidate window."; "xibGeneralSettings.title" = "General Settings"; "xibKeyboardShortcuts.title" = "Keyboard Shortcuts"; diff --git a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings index 68feaed8..7d2d2410 100644 --- a/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/ja.lproj/frmPrefWindow.strings @@ -115,6 +115,7 @@ "wN3-k3-b2a.title" = "欲しがるユーザー辞書保存先をご指定ください。無効の保存先設定は効かぬ。"; "wQ9-px-b07.title" = "弁音配列を起用していない限り、キーボード配置の設定はキーボードビューアの有りようだけに影響を及ぼす。"; "Wvt-HE-LOv.title" = "キーボード"; +"WX6-BW-JPM.title" = "このエディターの外部からの編集結果をこのエディターに自動的に読み込む"; "xC5-yV-1W1.title" = "入力候補陳列の仕様をご指定ください。"; "xibGeneralSettings.title" = "全般設定"; "xibKeyboardShortcuts.title" = "ショートカット"; diff --git a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings index bdc69ae9..49e5dadc 100644 --- a/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hans.lproj/frmPrefWindow.strings @@ -115,6 +115,7 @@ "wN3-k3-b2a.title" = "请在此指定您想指定的使用者语汇档案目录。无效值会被忽略。"; "wQ9-px-b07.title" = "如果当前的普通话/国音分析器并未设为拼音的话,则键盘布局选项仅会影响到荧幕键盘。"; "Wvt-HE-LOv.title" = "键盘布局"; +"WX6-BW-JPM.title" = "仅限该编辑器:自动读入来自该编辑器外部的档案内容修改"; "xC5-yV-1W1.title" = "选择您所偏好的候选字窗布局。"; "xibGeneralSettings.title" = "一般设定"; "xibKeyboardShortcuts.title" = "键盘热键"; diff --git a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings index ca17bf72..cbd4e567 100644 --- a/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings +++ b/Source/WindowNIBs/zh-Hant.lproj/frmPrefWindow.strings @@ -115,6 +115,7 @@ "wN3-k3-b2a.title" = "請在此指定您想指定的使用者語彙檔案目錄。無效值會被忽略。"; "wQ9-px-b07.title" = "如果當前的普通話/國音分析器並未設為拼音的話,則鍵盤佈局選項僅會影響到螢幕鍵盤。"; "Wvt-HE-LOv.title" = "鍵盤佈局"; +"WX6-BW-JPM.title" = "僅限該編輯器:自動讀入來自該編輯器外部的檔案內容修改"; "xC5-yV-1W1.title" = "選擇您所偏好的候選字窗佈局。"; "xibGeneralSettings.title" = "一般設定"; "xibKeyboardShortcuts.title" = "鍵盤熱鍵"; diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 85dcaad0..1142ce4d 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -74,6 +74,7 @@ 5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E01D28DDE4770094E427 /* NotifierUI */; }; 5BC5E02128DDEFE00094E427 /* TooltipUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02028DDEFE00094E427 /* TooltipUI */; }; 5BC5E02428DE07860094E427 /* PopupCompositionBuffer in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E02328DE07860094E427 /* PopupCompositionBuffer */; }; + 5BCC631629407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BCC631529407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift */; }; 5BCCAFF828DB19A300AB1B27 /* PrefMgr_Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BCCAFF728DB19A300AB1B27 /* PrefMgr_Extension.swift */; }; 5BD0113D2818543900609769 /* InputHandler_Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113C2818543900609769 /* InputHandler_Core.swift */; }; 5BD05BCA27B2A43D004C4F1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; }; @@ -280,6 +281,7 @@ 5BC5E01C28DDE4270094E427 /* vChewing_NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_NotifierUI; path = Packages/vChewing_NotifierUI; sourceTree = ""; }; 5BC5E01F28DDEFD80094E427 /* vChewing_TooltipUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_TooltipUI; path = Packages/vChewing_TooltipUI; sourceTree = ""; }; 5BC5E02228DE07250094E427 /* vChewing_PopupCompositionBuffer */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_PopupCompositionBuffer; path = Packages/vChewing_PopupCompositionBuffer; sourceTree = ""; }; + 5BCC631529407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CtlPrefWindow_PhraseEditor.swift; sourceTree = ""; }; 5BCCAFF728DB19A300AB1B27 /* PrefMgr_Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefMgr_Extension.swift; sourceTree = ""; }; 5BD0113C2818543900609769 /* InputHandler_Core.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = InputHandler_Core.swift; sourceTree = ""; usesTabs = 0; }; 5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewingPhraseEditor.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -502,6 +504,7 @@ 5B62A33C27AE7CC100A19448 /* CtlAboutWindow.swift */, 5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */, D47F7DCD278BFB57002F9DD7 /* CtlPrefWindow.swift */, + 5BCC631529407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift */, ); path = WindowControllers; sourceTree = ""; @@ -1186,6 +1189,7 @@ 5BE1F8A928F86AB5006C7FF5 /* InputHandler_HandleEvent.swift in Sources */, 5B69938C293B811F0057CB8E /* VwrPrefPanePhrases.swift in Sources */, 5BAEFAD028012565001F42C9 /* LMMgr.swift in Sources */, + 5BCC631629407BBB00A2D84F /* CtlPrefWindow_PhraseEditor.swift in Sources */, 5B782EC4280C243C007276DE /* InputHandler_HandleCandidate.swift in Sources */, 5BA9FD0F27FEDB6B002DE248 /* VwrPrefPaneGeneral.swift in Sources */, 5BCCAFF828DB19A300AB1B27 /* PrefMgr_Extension.swift in Sources */,