2.6.0 // Steam support, etc. Merge PR #131 from upd/2.6.0

This commit is contained in:
ShikiSuen 2022-09-11 19:35:18 +08:00 committed by GitHub
commit da9cccbb2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 811 additions and 206 deletions

View File

@ -17,7 +17,7 @@ $ Contributors and volunteers of the upstream repo, having no responsibility in
- Zonble Yang: - Zonble Yang:
- McBopomofo for macOS 2.x architect. - McBopomofo for macOS 2.x architect.
- Voltaire candidate window MK2 (massively modified as MK3 in vChewing by Shiki Suen). - Voltaire candidate window MK2 (massively modified as MK3 in vChewing by Shiki Suen).
- Notifier window and Tooltip UI. - Notifier window.
- App-style installer (only preserved for developer purposes). - App-style installer (only preserved for developer purposes).
- mgrPrefs (userdefaults manager). - mgrPrefs (userdefaults manager).
- Mengjuei Hsieh: - Mengjuei Hsieh:

View File

@ -101,6 +101,7 @@ class AppDelegate: NSWindowController, NSApplicationDelegate {
window.standardWindowButton(.closeButton)?.isHidden = true window.standardWindowButton(.closeButton)?.isHidden = true
window.standardWindowButton(.miniaturizeButton)?.isHidden = true window.standardWindowButton(.miniaturizeButton)?.isHidden = true
window.standardWindowButton(.zoomButton)?.isHidden = true window.standardWindowButton(.zoomButton)?.isHidden = true
window.titlebarAppearsTransparent = true
if FileManager.default.fileExists( if FileManager.default.fileExists(
atPath: kTargetPartialPath) atPath: kTargetPartialPath)

View File

@ -198,7 +198,7 @@ DQ
</textField> </textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XLb-mv-73s"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XLb-mv-73s">
<rect key="frame" x="89" y="387" width="431" height="15"/> <rect key="frame" x="89" y="387" width="431" height="15"/>
<textFieldCell key="cell" selectable="YES" title="Placeholder for detailed credits." id="VW8-s5-Wpn"> <textFieldCell key="cell" title="Placeholder for detailed credits." id="VW8-s5-Wpn">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -220,7 +220,7 @@ DQ
<constraints> <constraints>
<constraint firstAttribute="width" constant="356" id="pu3-zr-hJy"/> <constraint firstAttribute="width" constant="356" id="pu3-zr-hJy"/>
</constraints> </constraints>
<textFieldCell key="cell" selectable="YES" id="Q9M-ni-kUM"> <textFieldCell key="cell" id="Q9M-ni-kUM">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string> <string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>

View File

@ -65,9 +65,11 @@ public class NSAttributedTextView: NSView {
let isVertical: Bool = !(direction == .horizontal) let isVertical: Bool = !(direction == .horizontal)
newAttributes[.verticalGlyphForm] = isVertical newAttributes[.verticalGlyphForm] = isVertical
let newStyle: NSMutableParagraphStyle = newAttributes[.paragraphStyle] as! NSMutableParagraphStyle let newStyle: NSMutableParagraphStyle = newAttributes[.paragraphStyle] as! NSMutableParagraphStyle
if #available(macOS 10.13, *) {
newStyle.lineSpacing = isVertical ? (fontSize / -2) : fontSize * 0.1 newStyle.lineSpacing = isVertical ? (fontSize / -2) : fontSize * 0.1
newStyle.maximumLineHeight = fontSize newStyle.maximumLineHeight = fontSize * 1.1
newStyle.minimumLineHeight = fontSize newStyle.minimumLineHeight = fontSize * 1.1
}
newAttributes[.paragraphStyle] = newStyle newAttributes[.paragraphStyle] = newStyle
var text: String = text ?? "" var text: String = text ?? ""
if !(direction == .horizontal) { if !(direction == .horizontal) {

@ -1 +1 @@
Subproject commit 6dba7237957681bfa4c623ab5689248cc02bc7e6 Subproject commit eeff2e3f7073873c07b4011717e32430db01227f

View File

@ -25,6 +25,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
// let vChewingKeyLayoutBundle = Bundle.init(path: URL(fileURLWithPath: Bundle.main.resourcePath ?? "").appendingPathComponent("vChewingKeyLayout.bundle").path) // let vChewingKeyLayoutBundle = Bundle.init(path: URL(fileURLWithPath: Bundle.main.resourcePath ?? "").appendingPathComponent("vChewingKeyLayout.bundle").path)
@IBOutlet var window: NSWindow? @IBOutlet var window: NSWindow?
private var ctlClientListMgrInstance: ctlClientListMgr?
private var ctlPrefWindowInstance: ctlPrefWindow? private var ctlPrefWindowInstance: ctlPrefWindow?
private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window private var ctlAboutWindowInstance: ctlAboutWindow? // New About Window
public lazy var folderMonitor = FolderMonitor( public lazy var folderMonitor = FolderMonitor(
@ -80,6 +81,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
folderMonitor.startMonitoring() folderMonitor.startMonitoring()
} }
func showClientListMgr() {
if ctlClientListMgrInstance == nil {
ctlClientListMgrInstance = ctlClientListMgr.init(windowNibName: "frmClientListMgr")
}
ctlClientListMgrInstance?.window?.center()
ctlClientListMgrInstance?.window?.orderFrontRegardless() //
ctlClientListMgrInstance?.window?.level = .statusBar
ctlClientListMgrInstance?.window?.titlebarAppearsTransparent = true
NSApp.setActivationPolicy(.accessory)
}
func showPreferences() { func showPreferences() {
if ctlPrefWindowInstance == nil { if ctlPrefWindowInstance == nil {
ctlPrefWindowInstance = ctlPrefWindow.init(windowNibName: "frmPrefWindow") ctlPrefWindowInstance = ctlPrefWindow.init(windowNibName: "frmPrefWindow")
@ -99,6 +111,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
ctlAboutWindowInstance?.window?.center() ctlAboutWindowInstance?.window?.center()
ctlAboutWindowInstance?.window?.orderFrontRegardless() // ctlAboutWindowInstance?.window?.orderFrontRegardless() //
ctlAboutWindowInstance?.window?.level = .statusBar ctlAboutWindowInstance?.window?.level = .statusBar
ctlAboutWindowInstance?.window?.titlebarAppearsTransparent = true
NSApp.setActivationPolicy(.accessory) NSApp.setActivationPolicy(.accessory)
} }

View File

@ -113,6 +113,7 @@ extension IMEState {
// displayTextSegments // displayTextSegments
result.data.displayTextSegments = displayTextSegments result.data.displayTextSegments = displayTextSegments
result.data.cursor = cursor result.data.cursor = cursor
result.data.marker = cursor
return result return result
} }

View File

@ -9,13 +9,16 @@
import Foundation import Foundation
public struct StateData { public struct StateData {
var displayedText: String = "" { var displayedText: String = ""
didSet { var displayedTextConverted: String {
let result = IME.kanjiConversionIfRequired(displayedText) ///
if result.utf16.count == displayedText.utf16.count, result.count == displayedText.count { var result = IME.kanjiConversionIfRequired(displayedText)
displayedText = result if result.utf16.count != displayedText.utf16.count
} || result.count != displayedText.count
{
result = displayedText
} }
return result
} }
// MARK: Cursor & Marker & Range for UTF8 // MARK: Cursor & Marker & Range for UTF8
@ -86,7 +89,7 @@ public struct StateData {
var attributedStringNormal: NSAttributedString { var attributedStringNormal: NSAttributedString {
/// ///
/// JIS /// JIS
let attributedString = NSMutableAttributedString(string: displayedText) let attributedString = NSMutableAttributedString(string: displayedTextConverted)
var newBegin = 0 var newBegin = 0
for (i, neta) in displayTextSegments.enumerated() { for (i, neta) in displayTextSegments.enumerated() {
attributedString.setAttributes( attributedString.setAttributes(
@ -104,7 +107,7 @@ public struct StateData {
var attributedStringMarking: NSAttributedString { var attributedStringMarking: NSAttributedString {
/// ///
/// JIS /// JIS
let attributedString = NSMutableAttributedString(string: displayedText) let attributedString = NSMutableAttributedString(string: displayedTextConverted)
let end = u16MarkedRange.upperBound let end = u16MarkedRange.upperBound
attributedString.setAttributes( attributedString.setAttributes(
@ -130,7 +133,7 @@ public struct StateData {
], ],
range: NSRange( range: NSRange(
location: end, location: end,
length: displayedText.utf16.count - end length: displayedTextConverted.utf16.count - end
) )
) )
return attributedString return attributedString

View File

@ -438,3 +438,52 @@ public class KeyHandler {
} }
} }
} }
// MARK: - Components for Popup Composition Buffer (PCB) Window.
///
/// - Remark: IMKTextInput mgrPrefs
private let compositorWidthLimit = 20
extension KeyHandler {
///
///
///
///
/// 使
///
var commitOverflownComposition: String {
guard !compositor.walkedNodes.isEmpty,
compositor.width > compositorWidthLimit,
let identifier = delegate?.clientBundleIdentifier,
mgrPrefs.clientsIMKTextInputIncapable.contains(identifier)
else {
return ""
}
// Steam Client Identifier
var textToCommit = ""
while compositor.width > compositorWidthLimit {
var delta = compositor.width - compositorWidthLimit
let node = compositor.walkedNodes[0]
if node.isReadingMismatched {
delta = node.keyArray.count
textToCommit += node.currentPair.value
} else {
delta = min(delta, node.keyArray.count)
textToCommit += node.currentPair.value.charComponents[0..<delta].joined()
}
let newCursor = max(compositor.cursor - delta, 0)
compositor.cursor = 0
if !node.isReadingMismatched {
consolidateCursorContext(with: node.currentPair)
}
// Bigram
for _ in 0..<delta {
compositor.dropKey(direction: .front)
}
compositor.cursor = newCursor
walk()
}
return textToCommit
}
}

View File

@ -111,6 +111,9 @@ extension KeyHandler {
// //
walk() walk()
// App
let textToCommit = commitOverflownComposition
// //
fetchSuggestionsFromUOM(apply: true) fetchSuggestionsFromUOM(apply: true)
@ -118,7 +121,8 @@ extension KeyHandler {
composer.clear() composer.clear()
// updateClientdisplayedText() // updateClientdisplayedText()
let inputting = buildInputtingState var inputting = buildInputtingState
inputting.textToCommit = textToCommit
stateCallback(inputting) stateCallback(inputting)
/// ///

View File

@ -22,15 +22,19 @@ extension NSEvent {
isARepeat: Bool? = nil, isARepeat: Bool? = nil,
keyCode: UInt16? = nil keyCode: UInt16? = nil
) -> NSEvent? { ) -> NSEvent? {
NSEvent.keyEvent( let oldChars: String = {
if self.type == .flagsChanged { return "" }
return self.characters ?? ""
}()
return NSEvent.keyEvent(
with: type ?? self.type, with: type ?? self.type,
location: location ?? locationInWindow, location: location ?? locationInWindow,
modifierFlags: modifierFlags ?? self.modifierFlags, modifierFlags: modifierFlags ?? self.modifierFlags,
timestamp: timestamp ?? self.timestamp, timestamp: timestamp ?? self.timestamp,
windowNumber: windowNumber ?? self.windowNumber, windowNumber: windowNumber ?? self.windowNumber,
context: nil, context: nil,
characters: characters ?? self.characters ?? "", characters: characters ?? oldChars,
charactersIgnoringModifiers: charactersIgnoringModifiers ?? self.characters ?? "", charactersIgnoringModifiers: charactersIgnoringModifiers ?? characters ?? oldChars,
isARepeat: isARepeat ?? self.isARepeat, isARepeat: isARepeat ?? self.isARepeat,
keyCode: keyCode ?? self.keyCode keyCode: keyCode ?? self.keyCode
) )
@ -81,6 +85,8 @@ extension NSEvent: InputSignalProtocol {
} }
public var charCode: UInt16 { public var charCode: UInt16 {
guard type != .flagsChanged else { return 0 }
guard characters != nil else { return 0 }
// count > 0!isEmpty滿 // count > 0!isEmpty滿
guard !text.isEmpty else { return 0 } guard !text.isEmpty else { return 0 }
let scalars = text.unicodeScalars let scalars = text.unicodeScalars

View File

@ -16,59 +16,9 @@ extension ctlInputMethod {
/// - Parameter event: IMK /// - Parameter event: IMK
/// - Returns: `true` IMK`false` /// - Returns: `true` IMK`false`
func commonEventHandler(_ event: NSEvent) -> Bool { func commonEventHandler(_ event: NSEvent) -> Bool {
// Shift macOS 10.15 macOS
let shouldUseHandle: Bool = {
switch mgrPrefs.shiftKeyAccommodationBehavior {
case 0: return false
case 1: return IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
case 2: return true
default: return false
}
}()
if #available(macOS 10.15, *) {
if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode {
if !shouldUseHandle || (!rencentKeyHandledByKeyHandler && shouldUseHandle) {
NotifierController.notify(
message: NSLocalizedString("Alphanumerical Mode", comment: "") + "\n"
+ (toggleASCIIMode()
? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: ""))
)
}
if shouldUseHandle {
rencentKeyHandledByKeyHandler = false
}
return false
}
}
///
guard client() != nil else { return false }
var event = event
// 使 NSEvent Emacs NSEvent NSEvent
if event.isEmacsKey {
let verticalProcessing =
(state.isCandidateContainer)
? ctlInputMethod.isVerticalCandidateSituation : ctlInputMethod.isVerticalTypingSituation
event = event.convertFromEmacKeyEvent(isVerticalContext: verticalProcessing)
}
/// flags使 KeyHandler
/// flags
/// event.type == .flagsChanged return false
/// NSInternalInconsistencyException
if event.type == .flagsChanged { return false }
//
ctlInputMethod.areWeNerfing = event.modifierFlags.contains([.shift, .command])
// //
// KeyHandler // KeyHandler
if !event.charCode.isPrintable { if !event.charCode.isPrintable { return false }
return false
}
/// 調 /// 調
/// result bool IMK /// result bool IMK
@ -78,9 +28,43 @@ extension ctlInputMethod {
} errorCallback: { } errorCallback: {
clsSFX.beep() clsSFX.beep()
} }
if shouldUseHandle {
rencentKeyHandledByKeyHandler = result
}
return result return result
} }
/// handle() IMK
/// handle()
/// - Parameter event: IMK
/// - Returns: `true` IMK`false`
func imkCandidatesEventHandler(event eventToDeal: NSEvent) -> Bool? {
// IMK IMK
// interpretKeyEvents()
// - super.interpretKeyEvents()
// - delegate ctlInputMethod KeyHandler
if let imkCandidates = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK, imkCandidates.visible {
let event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: eventToDeal) ?? eventToDeal
// Shift+Enter delegate keyHandler
// Shift Flags
if event.isShiftHold, event.isEnter {
guard let newEvent = event.reinitiate(modifierFlags: []) else {
NSSound.beep()
return true
}
imkCandidates.interpretKeyEvents([newEvent])
return true
}
//
if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode],
event.isShiftHold, isAssociatedPhrasesState,
let newEvent = event.reinitiate(modifierFlags: [], characters: newChar)
{
imkCandidates.handleKeyboardEvent(newEvent)
}
imkCandidates.interpretKeyEvents([event])
return true
}
return nil
}
} }

View File

@ -27,9 +27,12 @@ class ctlInputMethod: IMKInputController {
static var ctlCandidateCurrent: ctlCandidateProtocol = static var ctlCandidateCurrent: ctlCandidateProtocol =
mgrPrefs.useIMKCandidateWindow ? ctlCandidateIMK.init(.horizontal) : ctlCandidateUniversal.init(.horizontal) mgrPrefs.useIMKCandidateWindow ? ctlCandidateIMK.init(.horizontal) : ctlCandidateUniversal.init(.horizontal)
/// ///
static var tooltipInstance = ctlTooltip() static var tooltipInstance = ctlTooltip()
///
static var popupCompositionBuffer = ctlPopupCompositionBuffer()
// MARK: - // MARK: -
/// ctlInputMethod /// ctlInputMethod
@ -57,7 +60,7 @@ class ctlInputMethod: IMKInputController {
} }
/// `handle(event:)` Shift /// `handle(event:)` Shift
var rencentKeyHandledByKeyHandler = false var rencentKeyHandledByKeyHandlerEtc = false
// MARK: - // MARK: -
@ -115,18 +118,7 @@ class ctlInputMethod: IMKInputController {
keyHandler.clear() // handle State.Empty() keyHandler.clear() // handle State.Empty()
keyHandler.ensureParser() keyHandler.ensureParser()
if isASCIIMode { if isASCIIMode, mgrPrefs.disableShiftTogglingAlphanumericalMode { isASCIIMode = false }
if mgrPrefs.disableShiftTogglingAlphanumericalMode {
isASCIIMode = false
} else {
NotifierController.notify(
message: NSLocalizedString("Alphanumerical Mode", comment: "") + "\n"
+ (isASCIIMode
? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: ""))
)
}
}
/// ///
/// macOS /// macOS
@ -207,6 +199,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 //
// MARK:
// //
ctlInputMethod.isASCIIModeSituation = isASCIIMode ctlInputMethod.isASCIIModeSituation = isASCIIMode
ctlInputMethod.isVerticalTypingSituation = isVerticalTyping ctlInputMethod.isVerticalTypingSituation = isVerticalTyping
@ -218,44 +212,72 @@ class ctlInputMethod: IMKInputController {
return false return false
} }
// IMK IMK // Shift macOS 10.15 macOS
// interpretKeyEvents() let shouldUseShiftToggleHandle: Bool = {
// - super.interpretKeyEvents() switch mgrPrefs.shiftKeyAccommodationBehavior {
// - delegate ctlInputMethod KeyHandler case 0: return false
proc: if let ctlCandidateCurrent = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK { case 1: return IME.arrClientShiftHandlingExceptionList.contains(clientBundleIdentifier)
guard ctlCandidateCurrent.visible else { break proc } case 2: return true
var event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: event) ?? event default: return false
// 使 NSEvent Emacs NSEvent NSEvent
if event.isEmacsKey {
event = event.convertFromEmacKeyEvent(isVerticalContext: ctlInputMethod.isVerticalCandidateSituation)
} }
}()
// Shift+Enter delegate keyHandler
// Shift Flags
if event.isShiftHold, event.isEnter {
guard let newEvent = event.reinitiate(modifierFlags: []) else {
NSSound.beep()
return true
}
ctlCandidateCurrent.interpretKeyEvents([newEvent])
return true
}
//
if let newChar = ctlCandidateIMK.defaultIMKSelectionKey[event.keyCode], event.isShiftHold,
isAssociatedPhrasesState, let newEvent = event.reinitiate(modifierFlags: [], characters: newChar)
{
ctlCandidateCurrent.handleKeyboardEvent(newEvent)
}
ctlCandidateCurrent.interpretKeyEvents([event])
return true
}
/// commonEventHandler
/// IMK 便
/// event event var Shift /// event event var Shift
return commonEventHandler(event) if #available(macOS 10.15, *) {
if ShiftKeyUpChecker.check(event), !mgrPrefs.disableShiftTogglingAlphanumericalMode {
if !shouldUseShiftToggleHandle || (!rencentKeyHandledByKeyHandlerEtc && shouldUseShiftToggleHandle) {
NotifierController.notify(
message: NSLocalizedString("Alphanumerical Mode", comment: "") + "\n"
+ (toggleASCIIMode()
? NSLocalizedString("NotificationSwitchON", comment: "")
: NSLocalizedString("NotificationSwitchOFF", comment: ""))
)
}
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = false
}
return false
}
}
// MARK:
/// flags使 KeyHandler
/// flags
/// event.type == .flagsChanged return false
/// NSInternalInconsistencyException
if event.type == .flagsChanged { return false }
///
guard client() != nil else { return false }
var eventToDeal = event
// 使 NSEvent Emacs NSEvent NSEvent
if eventToDeal.isEmacsKey {
let verticalProcessing =
(state.isCandidateContainer)
? ctlInputMethod.isVerticalCandidateSituation : ctlInputMethod.isVerticalTypingSituation
eventToDeal = eventToDeal.convertFromEmacKeyEvent(isVerticalContext: verticalProcessing)
}
//
ctlInputMethod.areWeNerfing = eventToDeal.modifierFlags.contains([.shift, .command])
// IMK IMK
if let result = imkCandidatesEventHandler(event: eventToDeal) {
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = result
}
return result
}
/// NSEvent commonEventHandler
/// IMK 便
let result = commonEventHandler(eventToDeal)
if shouldUseShiftToggleHandle {
rencentKeyHandledByKeyHandlerEtc = result
}
return result
} }
/// App Ctrl+Enter / Shift+Enter /// App Ctrl+Enter / Shift+Enter

View File

@ -16,7 +16,7 @@ extension ctlInputMethod: KeyHandlerDelegate {
/// ///
public var isVerticalTyping: Bool { public var isVerticalTyping: Bool {
guard let client = client() else { return false } guard let client = client() else { return false }
var textFrame = NSRect.zero var textFrame = NSRect.seniorTheBeast
let attributes: [AnyHashable: Any]? = client.attributes( let attributes: [AnyHashable: Any]? = client.attributes(
forCharacterIndex: 0, lineHeightRectangle: &textFrame forCharacterIndex: 0, lineHeightRectangle: &textFrame
) )

View File

@ -13,19 +13,31 @@ import Cocoa
// MARK: - Tooltip Display and Candidate Display Methods // MARK: - Tooltip Display and Candidate Display Methods
extension ctlInputMethod { extension ctlInputMethod {
func show(tooltip: String, displayedText: String, u16Cursor: Int) { func lineHeightRect(zeroCursor: Bool = false) -> NSRect {
guard let client = client() else { return } var lineHeightRect = NSRect.seniorTheBeast
var lineHeightRect = NSRect(x: 0.0, y: 0.0, width: 16.0, height: 16.0) guard let client = client() else {
var cursor = u16Cursor return lineHeightRect
if cursor == displayedText.count, cursor != 0 {
cursor -= 1
} }
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 { var u16Cursor: Int = {
// iMessage cursor == 0
if clientBundleIdentifier == "com.apple.MobileSMS" { return state.data.u16Cursor }
if state.data.marker >= state.data.cursor { return state.data.u16Cursor }
return state.data.u16Marker //
}()
u16Cursor = max(min(state.data.displayedTextConverted.utf16.count, u16Cursor), 0)
if zeroCursor { u16Cursor = 0 }
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, u16Cursor >= 0 {
client.attributes( client.attributes(
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect forCharacterIndex: u16Cursor, lineHeightRectangle: &lineHeightRect
) )
cursor -= 1 u16Cursor -= 1
} }
return lineHeightRect
}
func show(tooltip: String) {
guard client() != nil else { return }
let lineHeightRect = lineHeightRect()
var finalOrigin: NSPoint = lineHeightRect.origin var finalOrigin: NSPoint = lineHeightRect.origin
let delta: CGFloat = lineHeightRect.size.height + 4.0 // bottomOutOfScreenAdjustmentHeight let delta: CGFloat = lineHeightRect.size.height + 4.0 // bottomOutOfScreenAdjustmentHeight
if isVerticalTyping { if isVerticalTyping {
@ -120,34 +132,17 @@ extension ctlInputMethod {
ctlInputMethod.ctlCandidateCurrent.visible = true ctlInputMethod.ctlCandidateCurrent.visible = true
var lineHeightRect = NSRect(x: 0.0, y: 0.0, width: 16.0, height: 16.0)
var cursor = 0
if [.ofCandidates, .ofSymbolTable].contains(state.type) {
cursor = state.data.cursor
if cursor == state.displayedText.count, cursor != 0 {
cursor -= 1
}
}
while lineHeightRect.origin.x == 0, lineHeightRect.origin.y == 0, cursor >= 0 {
client.attributes(
forCharacterIndex: cursor, lineHeightRectangle: &lineHeightRect
)
cursor -= 1
}
if isVerticalTyping { if isVerticalTyping {
ctlInputMethod.ctlCandidateCurrent.set( ctlInputMethod.ctlCandidateCurrent.set(
windowTopLeftPoint: NSPoint( windowTopLeftPoint: NSPoint(
x: lineHeightRect.origin.x + lineHeightRect.size.width + 4.0, y: lineHeightRect.origin.y - 4.0 x: lineHeightRect().origin.x + lineHeightRect().size.width + 4.0, y: lineHeightRect().origin.y - 4.0
), ),
bottomOutOfScreenAdjustmentHeight: lineHeightRect.size.height + 4.0 bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0
) )
} else { } else {
ctlInputMethod.ctlCandidateCurrent.set( ctlInputMethod.ctlCandidateCurrent.set(
windowTopLeftPoint: NSPoint(x: lineHeightRect.origin.x, y: lineHeightRect.origin.y - 4.0), windowTopLeftPoint: NSPoint(x: lineHeightRect().origin.x, y: lineHeightRect().origin.y - 4.0),
bottomOutOfScreenAdjustmentHeight: lineHeightRect.size.height + 4.0 bottomOutOfScreenAdjustmentHeight: lineHeightRect().size.height + 4.0
) )
} }
} }

View File

@ -65,10 +65,7 @@ extension ctlInputMethod {
if !textToCommit.isEmpty { commit(text: textToCommit) } if !textToCommit.isEmpty { commit(text: textToCommit) }
setInlineDisplayWithCursor() setInlineDisplayWithCursor()
if !state.tooltip.isEmpty { if !state.tooltip.isEmpty {
show( show(tooltip: state.tooltip)
tooltip: state.tooltip, displayedText: state.displayedText,
u16Cursor: state.data.u16Cursor
)
} }
case .ofMarking: case .ofMarking:
ctlInputMethod.ctlCandidateCurrent.visible = false ctlInputMethod.ctlCandidateCurrent.visible = false
@ -76,14 +73,7 @@ extension ctlInputMethod {
if state.tooltip.isEmpty { if state.tooltip.isEmpty {
ctlInputMethod.tooltipInstance.hide() ctlInputMethod.tooltipInstance.hide()
} else { } else {
let cursorReference: Int = { show(tooltip: state.tooltip)
if state.data.marker >= state.data.cursor { return state.data.u16Cursor }
return state.data.u16Marker //
}()
show(
tooltip: state.tooltip, displayedText: state.displayedText,
u16Cursor: cursorReference
)
} }
case .ofCandidates, .ofAssociates, .ofSymbolTable: case .ofCandidates, .ofAssociates, .ofSymbolTable:
ctlInputMethod.tooltipInstance.hide() ctlInputMethod.tooltipInstance.hide()
@ -91,6 +81,14 @@ extension ctlInputMethod {
show(candidateWindowWith: state) show(candidateWindowWith: state)
default: break default: break
} }
//
if state.hasComposition, mgrPrefs.clientsIMKTextInputIncapable.contains(clientBundleIdentifier) {
ctlInputMethod.popupCompositionBuffer.show(
state: state, at: lineHeightRect(zeroCursor: true).origin
)
} else {
ctlInputMethod.popupCompositionBuffer.hide()
}
} }
/// .NotEmpty() /// .NotEmpty()
@ -109,7 +107,7 @@ extension ctlInputMethod {
/// 0 replacementRangeNSNotFound /// 0 replacementRangeNSNotFound
/// ///
client.setMarkedText( client.setMarkedText(
state.attributedString, selectionRange: NSRange(location: state.data.u16Cursor, length: 0), state.attributedString, selectionRange: NSRange(state.data.u16MarkedRange),
replacementRange: NSRange(location: NSNotFound, length: NSNotFound) replacementRange: NSRange(location: NSNotFound, length: NSNotFound)
) )
return return

View File

@ -156,6 +156,12 @@ extension ctlInputMethod {
withTitle: NSLocalizedString("vChewing Preferences…", comment: ""), withTitle: NSLocalizedString("vChewing Preferences…", comment: ""),
action: #selector(showPreferences(_:)), keyEquivalent: "" action: #selector(showPreferences(_:)), keyEquivalent: ""
) )
}
menu.addItem(
withTitle: NSLocalizedString("Client Manager", comment: "") + "",
action: #selector(showClientListMgr(_:)), keyEquivalent: ""
)
if !optionKeyPressed {
menu.addItem( menu.addItem(
withTitle: NSLocalizedString("Check for Updates…", comment: ""), withTitle: NSLocalizedString("Check for Updates…", comment: ""),
action: #selector(checkForUpdate(_:)), keyEquivalent: "" action: #selector(checkForUpdate(_:)), keyEquivalent: ""
@ -208,6 +214,11 @@ extension ctlInputMethod {
NSWorkspace.shared.openFile(url.path, withApplication: "Safari") NSWorkspace.shared.openFile(url.path, withApplication: "Safari")
} }
@objc func showClientListMgr(_: Any?) {
(NSApp.delegate as? AppDelegate)?.showClientListMgr()
NSApp.activate(ignoringOtherApps: true)
}
@objc func toggleSCPCTypingMode(_: Any? = nil) { @objc func toggleSCPCTypingMode(_: Any? = nil) {
resetKeyHandler() resetKeyHandler()
NotifierController.notify( NotifierController.notify(

View File

@ -348,3 +348,11 @@ extension NSApplication {
return output return output
} }
} }
// MARK: NSRect Extension
extension NSRect {
public static var seniorTheBeast: NSRect {
NSRect(x: 0.0, y: 0.0, width: 0.114, height: 0.514)
}
}

View File

@ -152,7 +152,7 @@ class UpdateSputnik: NSObject, URLSessionDataDelegate {
let content = NSLocalizedString(message, comment: "") let content = NSLocalizedString(message, comment: "")
alert.messageText = NSLocalizedString("Update Check Failed", comment: "") alert.messageText = NSLocalizedString("Update Check Failed", comment: "")
alert.informativeText = content alert.informativeText = content
alert.addButton(withTitle: NSLocalizedString("Dismiss", comment: "")) alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
alert.runModal() alert.runModal()
NSApp.setActivationPolicy(.accessory) NSApp.setActivationPolicy(.accessory)
} }

View File

@ -56,6 +56,7 @@ public enum UserDef: String, CaseIterable {
case kHardenVerticalPunctuations = "HardenVerticalPunctuations" case kHardenVerticalPunctuations = "HardenVerticalPunctuations"
case kTrimUnfinishedReadingsOnCommit = "TrimUnfinishedReadingsOnCommit" case kTrimUnfinishedReadingsOnCommit = "TrimUnfinishedReadingsOnCommit"
case kAlwaysShowTooltipTextsHorizontally = "AlwaysShowTooltipTextsHorizontally" case kAlwaysShowTooltipTextsHorizontally = "AlwaysShowTooltipTextsHorizontally"
case kClientsIMKTextInputIncapable = "ClientsIMKTextInputIncapable"
case kUseIMKCandidateWindow = "UseIMKCandidateWindow" case kUseIMKCandidateWindow = "UseIMKCandidateWindow"
case kHandleDefaultCandidateFontsByLangIdentifier = "HandleDefaultCandidateFontsByLangIdentifier" case kHandleDefaultCandidateFontsByLangIdentifier = "HandleDefaultCandidateFontsByLangIdentifier"
@ -306,6 +307,9 @@ public enum mgrPrefs {
UserDefaults.standard.setDefault( UserDefaults.standard.setDefault(
mgrPrefs.trimUnfinishedReadingsOnCommit, forKey: UserDef.kTrimUnfinishedReadingsOnCommit.rawValue mgrPrefs.trimUnfinishedReadingsOnCommit, forKey: UserDef.kTrimUnfinishedReadingsOnCommit.rawValue
) )
UserDefaults.standard.setDefault(
mgrPrefs.clientsIMKTextInputIncapable, forKey: UserDef.kClientsIMKTextInputIncapable.rawValue
)
// ----- // -----
@ -443,6 +447,9 @@ public enum mgrPrefs {
@UserDefault(key: UserDef.kAlwaysShowTooltipTextsHorizontally.rawValue, defaultValue: false) @UserDefault(key: UserDef.kAlwaysShowTooltipTextsHorizontally.rawValue, defaultValue: false)
static var alwaysShowTooltipTextsHorizontally: Bool static var alwaysShowTooltipTextsHorizontally: Bool
@UserDefault(key: UserDef.kClientsIMKTextInputIncapable.rawValue, defaultValue: ["com.valvesoftware.steam"])
static var clientsIMKTextInputIncapable: [String]
// MARK: - Settings (Tier 2) // MARK: - Settings (Tier 2)
@UserDefault(key: UserDef.kUseIMKCandidateWindow.rawValue, defaultValue: false) @UserDefault(key: UserDef.kUseIMKCandidateWindow.rawValue, defaultValue: false)
@ -738,6 +745,8 @@ extension mgrPrefs {
mgrPrefs.disableShiftTogglingAlphanumericalMode = false mgrPrefs.disableShiftTogglingAlphanumericalMode = false
mgrPrefs.togglingAlphanumericalModeWithLShift = false mgrPrefs.togglingAlphanumericalModeWithLShift = false
} }
//
clientsIMKTextInputIncapable = Array(Set(clientsIMKTextInputIncapable)).sorted()
// //
var isMandarinParserOptionValid = false var isMandarinParserOptionValid = false
MandarinParser.allCases.forEach { MandarinParser.allCases.forEach {

View File

@ -160,7 +160,7 @@ public class ctlCandidate: NSWindowController, ctlCandidateProtocol {
var adjustedPoint = windowTopLeftPoint var adjustedPoint = windowTopLeftPoint
var delta = heightDelta var delta = heightDelta
var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.zero var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowTopLeftPoint) }) { for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowTopLeftPoint) }) {
screenFrame = frame screenFrame = frame
break break

View File

@ -167,7 +167,7 @@ public class ctlCandidateIMK: IMKCandidates, ctlCandidateProtocol {
var adjustedPoint = windowTopLeftPoint var adjustedPoint = windowTopLeftPoint
var adjustedHeight = height var adjustedHeight = height
var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.zero var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
for screen in NSScreen.screens { for screen in NSScreen.screens {
let frame = screen.visibleFrame let frame = screen.visibleFrame
if windowTopLeftPoint.x >= frame.minX, windowTopLeftPoint.x <= frame.maxX, if windowTopLeftPoint.x >= frame.minX, windowTopLeftPoint.x <= frame.maxX,

View File

@ -346,7 +346,7 @@ public class ctlCandidateUniversal: ctlCandidate {
let panel = NSPanel( let panel = NSPanel(
contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false
) )
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1) panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 2)
panel.hasShadow = true panel.hasShadow = true
panel.isOpaque = false panel.isOpaque = false
panel.backgroundColor = NSColor.clear panel.backgroundColor = NSColor.clear
@ -600,7 +600,7 @@ extension ctlCandidateUniversal {
pageCounterLabel.isHidden = true pageCounterLabel.isHidden = true
} }
frameRect = window?.frame ?? NSRect.zero frameRect = window?.frame ?? NSRect.seniorTheBeast
let topLeftPoint = NSPoint(x: frameRect.origin.x, y: frameRect.origin.y + frameRect.size.height) let topLeftPoint = NSPoint(x: frameRect.origin.x, y: frameRect.origin.y + frameRect.size.height)
frameRect.size = newSize frameRect.size = newSize

View File

@ -90,7 +90,7 @@ public class NotifierController: NSWindowController, NotifierWindowDelegate {
} }
private init() { private init() {
let screenRect = NSScreen.main?.visibleFrame ?? NSRect.zero let screenRect = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
let contentRect = NSRect(x: 0, y: 0, width: kWindowWidth, height: kWindowHeight) let contentRect = NSRect(x: 0, y: 0, width: kWindowWidth, height: kWindowHeight)
var windowRect = contentRect var windowRect = contentRect
windowRect.origin.x = screenRect.maxX - windowRect.width - 10 windowRect.origin.x = screenRect.maxX - windowRect.width - 10
@ -144,8 +144,8 @@ public class NotifierController: NSWindowController, NotifierWindowDelegate {
return return
} }
let lastLocation = NotifierController.lastLocation let lastLocation = NotifierController.lastLocation
let screenRect = NSScreen.main?.visibleFrame ?? NSRect.zero let screenRect = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
var windowRect = window?.frame ?? NSRect.zero var windowRect = window?.frame ?? NSRect.seniorTheBeast
windowRect.origin.x = lastLocation.x windowRect.origin.x = lastLocation.x
windowRect.origin.y = lastLocation.y - 10 - windowRect.height windowRect.origin.y = lastLocation.y - 10 - windowRect.height
@ -157,7 +157,7 @@ public class NotifierController: NSWindowController, NotifierWindowDelegate {
} }
func moveIn() { func moveIn() {
let afterRect = window?.frame ?? NSRect.zero let afterRect = window?.frame ?? NSRect.seniorTheBeast
NotifierController.lastLocation = afterRect.origin NotifierController.lastLocation = afterRect.origin
var beforeRect = afterRect var beforeRect = afterRect
beforeRect.origin.y += 10 beforeRect.origin.y += 10

View File

@ -0,0 +1,127 @@
// (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 Cocoa
public class ctlPopupCompositionBuffer: NSWindowController {
private var messageTextField: NSTextField
private var textShown: NSAttributedString = .init(string: "") {
didSet {
messageTextField.attributedStringValue = textShown
adjustSize()
}
}
public init() {
let transparentVisualEffect = NSVisualEffectView()
transparentVisualEffect.blendingMode = .behindWindow
transparentVisualEffect.state = .active
let contentRect = NSRect(x: 128.0, y: 128.0, width: 300.0, height: 20.0)
let styleMask: NSWindow.StyleMask = [.borderless, .nonactivatingPanel]
let panel = NSPanel(
contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false
)
panel.contentView = transparentVisualEffect
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1)
panel.hasShadow = true
panel.backgroundColor = NSColor.clear
messageTextField = NSTextField()
messageTextField.isEditable = false
messageTextField.isSelectable = false
messageTextField.isBezeled = false
messageTextField.textColor = NSColor.textColor
messageTextField.drawsBackground = true
messageTextField.backgroundColor = NSColor.clear
messageTextField.font = .systemFont(ofSize: 18)
panel.contentView?.addSubview(messageTextField)
super.init(window: panel)
}
@available(*, unavailable)
public required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func show(state: IMEStateProtocol, at point: NSPoint) {
if !state.hasComposition {
hide()
return
}
//
let attrString: NSMutableAttributedString = .init(string: state.data.displayedTextConverted)
attrString.setAttributes(
[
.backgroundColor: NSColor.alternateSelectedControlColor,
.foregroundColor: NSColor.alternateSelectedControlTextColor,
.markedClauseSegment: 0,
],
range: NSRange(
location: state.data.u16MarkedRange.lowerBound,
length: state.data.u16MarkedRange.upperBound - state.data.u16MarkedRange.lowerBound
)
)
let attrCursor = NSMutableAttributedString(string: "_")
if #available(macOS 10.13, *) {
attrCursor.setAttributes(
[
.kern: -18,
.baselineOffset: -2,
.markedClauseSegment: 1,
],
range: NSRange(location: 0, length: attrCursor.string.utf16.count)
)
}
attrString.insert(attrCursor, at: state.data.u16Cursor)
textShown = attrString
messageTextField.maximumNumberOfLines = 1
if let editor = messageTextField.currentEditor() {
editor.selectedRange = NSRange(state.data.u16MarkedRange)
}
window?.orderFront(nil)
set(windowOrigin: point)
}
public func hide() {
window?.orderOut(nil)
}
private func set(windowOrigin: NSPoint) {
guard let window = window else { return }
let windowSize = window.frame.size
var adjustedPoint = windowOrigin
var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowOrigin) }) {
screenFrame = frame
break
}
adjustedPoint.y = min(max(adjustedPoint.y, screenFrame.minY + windowSize.height), screenFrame.maxY)
adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width)
window.setFrameOrigin(adjustedPoint)
}
private func adjustSize() {
let attrString = messageTextField.attributedStringValue
var rect = attrString.boundingRect(
with: NSSize(width: 1600.0, height: 1600.0),
options: [.usesLineFragmentOrigin, .usesFontLeading]
)
rect.size.width = max(rect.size.width, 20 * CGFloat(attrString.string.count)) + 2
rect.size.height = 22
var bigRect = rect
bigRect.size.width += NSFont.systemFontSize
bigRect.size.height += NSFont.systemFontSize
rect.origin.x += NSFont.systemFontSize / 2
rect.origin.y += NSFont.systemFontSize / 2
messageTextField.frame = rect
window?.setFrame(bigRect, display: true)
}
}

View File

@ -40,7 +40,7 @@ public class ctlTooltip: NSWindowController {
let panel = NSPanel( let panel = NSPanel(
contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false contentRect: contentRect, styleMask: styleMask, backing: .buffered, defer: false
) )
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1) panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 2)
panel.hasShadow = true panel.hasShadow = true
panel.backgroundColor = NSColor.controlBackgroundColor panel.backgroundColor = NSColor.controlBackgroundColor
messageText = NSAttributedTextView() messageText = NSAttributedTextView()
@ -129,7 +129,7 @@ public class ctlTooltip: NSWindowController {
var adjustedPoint = windowTopLeftPoint var adjustedPoint = windowTopLeftPoint
var delta = heightDelta var delta = heightDelta
var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.zero var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowTopLeftPoint) }) { for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowTopLeftPoint) }) {
screenFrame = frame screenFrame = frame
break break

View File

@ -1,4 +1,15 @@
"vChewing" = "vChewing"; "vChewing" = "vChewing";
"Please enter the client app bundle identifier(s) you want to register." = "Please enter the client app bundle identifier(s) you want to register.";
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.";
"Just Select" = "Just Select";
"Client Manager" = "Client Manager";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable.";
"Add Client" = "Add Client";
"Remove Selected" = "Remove Selected";
"Choose the target application bundle." = "Choose the target application bundle.";
"The selected item is not a valid macOS application bundle." = "The selected item is not a valid macOS application bundle.";
"Please try again." = "Please try again.";
"The selected item's identifier is already in the list." = "The selected item's identifier is already in the list.";
"Update Check Completed" = "Update Check Completed"; "Update Check Completed" = "Update Check Completed";
"You are already using the latest version." = "You are already using the latest version."; "You are already using the latest version." = "You are already using the latest version.";
"Plist downloaded is nil." = "Plist downloaded is nil."; "Plist downloaded is nil." = "Plist downloaded is nil.";
@ -17,7 +28,7 @@
"Update Check Failed" = "Update Check Failed"; "Update Check Failed" = "Update Check Failed";
"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "There may be no internet connection or the server failed to respond.\n\nError message: %@"; "There may be no internet connection or the server failed to respond.\n\nError message: %@" = "There may be no internet connection or the server failed to respond.\n\nError message: %@";
"OK" = "OK"; "OK" = "OK";
"Dismiss" = "Dismiss"; "Cancel" = "Cancel";
"New Version Available" = "New Version Available"; "New Version Available" = "New Version Available";
"Not Now" = "Not Now"; "Not Now" = "Not Now";
"Visit Website" = "Visit Website"; "Visit Website" = "Visit Website";

View File

@ -1,4 +1,15 @@
"vChewing" = "vChewing"; "vChewing" = "vChewing";
"Please enter the client app bundle identifier(s) you want to register." = "Please enter the client app bundle identifier(s) you want to register.";
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.";
"Just Select" = "Just Select";
"Client Manager" = "Client Manager";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable.";
"Add Client" = "Add Client";
"Remove Selected" = "Remove Selected";
"Choose the target application bundle." = "Choose the target application bundle.";
"The selected item is not a valid macOS application bundle." = "The selected item is not a valid macOS application bundle.";
"Please try again." = "Please try again.";
"The selected item's identifier is already in the list." = "The selected item's identifier is already in the list.";
"Update Check Completed" = "Update Check Completed"; "Update Check Completed" = "Update Check Completed";
"You are already using the latest version." = "You are already using the latest version."; "You are already using the latest version." = "You are already using the latest version.";
"Plist downloaded is nil." = "Plist downloaded is nil."; "Plist downloaded is nil." = "Plist downloaded is nil.";
@ -17,7 +28,7 @@
"Update Check Failed" = "Update Check Failed"; "Update Check Failed" = "Update Check Failed";
"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "There may be no internet connection or the server failed to respond.\n\nError message: %@"; "There may be no internet connection or the server failed to respond.\n\nError message: %@" = "There may be no internet connection or the server failed to respond.\n\nError message: %@";
"OK" = "OK"; "OK" = "OK";
"Dismiss" = "Dismiss"; "Cancel" = "Cancel";
"New Version Available" = "New Version Available"; "New Version Available" = "New Version Available";
"Not Now" = "Not Now"; "Not Now" = "Not Now";
"Visit Website" = "Visit Website"; "Visit Website" = "Visit Website";

View File

@ -1,4 +1,15 @@
"vChewing" = "威注音入力アプリ"; "vChewing" = "威注音入力アプリ";
"Please enter the client app bundle identifier(s) you want to register." = "登録したい客体アプリの唯一識別子Bundle Identifierをご入力ください。";
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "毎行はつ記録とみなす。Option+Enter キーで改行。\n空白の記録値は無視される。";
"Just Select" = "直接に選ぶ";
"Client Manager" = "客体アプリの管理";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "IMKTextInput 議定規約に従っていない客体アプリはここでご登録ください。登録済みのアプリは客体アプリ(文字入力を受くアプリ)とされた時に、威注音入力アプリは「吹き出し入力緩衝列ウィンドウ」と「緩衝列容量制限」を起用し、その容量制限は最大限音読み20箇とする。";
"Add Client" = "入れる";
"Remove Selected" = "外す";
"Choose the target application bundle." = "登録したいアプリのバンドルのお選びを。";
"The selected item is not a valid macOS application bundle." = "今選んだんのは正しい macOS アプリバンドルではないと考えられる。";
"Please try again." = "お選び直しください。";
"The selected item's identifier is already in the list." = "今選んだバンドルの唯一識別子Bundle Identifierは既に登録済みである。";
"Update Check Completed" = "新バージョンチェック完了"; "Update Check Completed" = "新バージョンチェック完了";
"You are already using the latest version." = "現在稼働中のは最新バージョンである。"; "You are already using the latest version." = "現在稼働中のは最新バージョンである。";
"Plist downloaded is nil." = "受けた新バージョンお知らせ情報データは Plist ではないため、失敗とみなす。"; "Plist downloaded is nil." = "受けた新バージョンお知らせ情報データは Plist ではないため、失敗とみなす。";
@ -17,7 +28,7 @@
"Update Check Failed" = "更新通知受信失敗"; "Update Check Failed" = "更新通知受信失敗";
"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "ネットの接続の有無の問題か、サーバー側の反応の問題か。\n\nいずれにせよ、エラーメッセージ「%@」"; "There may be no internet connection or the server failed to respond.\n\nError message: %@" = "ネットの接続の有無の問題か、サーバー側の反応の問題か。\n\nいずれにせよ、エラーメッセージ「%@」";
"OK" = "うむ"; "OK" = "うむ";
"Dismiss" = "却下"; "Cancel" = "取り消す";
"New Version Available" = "最新版利用可能"; "New Version Available" = "最新版利用可能";
"Not Now" = "後で"; "Not Now" = "後で";
"Visit Website" = "公式サイト"; "Visit Website" = "公式サイト";

View File

@ -1,4 +1,15 @@
"vChewing" = "威注音输入法"; "vChewing" = "威注音输入法";
"Please enter the client app bundle identifier(s) you want to register." = "请键入您要登记的客体应用的唯一标帜Bundle Identifier。";
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一笔记录,用 Option+Enter 换行。\n空白值会被无视。";
"Just Select" = "直接选取";
"Client Manager" = "管理客体应用";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "请在此管理那些不遵守 IMKTextInput 协定的客体应用。威注音输入法对于任何位列在此的客体应用均启用浮动组字窗、且对组字区内容设定容量上限(最多二十个读音)。";
"Add Client" = "登记新客体";
"Remove Selected" = "移除所选条目";
"Choose the target application bundle." = "请选择要登记的应用程式的封包。";
"The selected item is not a valid macOS application bundle." = "当前所选之物并非 macOS 应用程式封包。";
"Please try again." = "请重试。";
"The selected item's identifier is already in the list." = "当前所选之封包的唯一标帜Bundle Identifier已被登记。";
"Update Check Completed" = "更新检查完毕"; "Update Check Completed" = "更新检查完毕";
"You are already using the latest version." = "您正在使用目前最新的发行版。"; "You are already using the latest version." = "您正在使用目前最新的发行版。";
"Plist downloaded is nil." = "下载来的更新资讯并非 Plist 档案。"; "Plist downloaded is nil." = "下载来的更新资讯并非 Plist 档案。";
@ -17,7 +28,7 @@
"Update Check Failed" = "无法检查新版"; "Update Check Failed" = "无法检查新版";
"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "网路连线失败,或是伺服器没有回应。\n\n错误说明%@"; "There may be no internet connection or the server failed to respond.\n\nError message: %@" = "网路连线失败,或是伺服器没有回应。\n\n错误说明%@";
"OK" = "确定"; "OK" = "确定";
"Dismiss" = "关闭本视窗"; "Cancel" = "取消";
"New Version Available" = "有新版可下载"; "New Version Available" = "有新版可下载";
"Not Now" = "以后再说"; "Not Now" = "以后再说";
"Visit Website" = "前往网站"; "Visit Website" = "前往网站";

View File

@ -1,4 +1,15 @@
"vChewing" = "威注音輸入法"; "vChewing" = "威注音輸入法";
"Please enter the client app bundle identifier(s) you want to register." = "請鍵入您要登記的客體應用的唯一標幟Bundle Identifier。";
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed." = "每行一筆記錄,用 Option+Enter 換行。\n空白值會被無視。";
"Just Select" = "直接選取";
"Client Manager" = "管理客體應用";
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable." = "請在此管理那些不遵守 IMKTextInput 協定的客體應用。威注音輸入法對於任何位列在此的客體應用均啟用浮動組字窗、且對組字區內容設定容量上限(最多二十個讀音)。";
"Add Client" = "登記新客體";
"Remove Selected" = "移除所選條目";
"Choose the target application bundle." = "請選擇要登記的應用程式的封包。";
"The selected item is not a valid macOS application bundle." = "當前所選之物並非 macOS 應用程式封包。";
"Please try again." = "請重試。";
"The selected item's identifier is already in the list." = "當前所選之封包的唯一標幟Bundle Identifier已被登記。";
"Update Check Completed" = "更新檢查完畢"; "Update Check Completed" = "更新檢查完畢";
"You are already using the latest version." = "您正在使用目前最新的發行版。"; "You are already using the latest version." = "您正在使用目前最新的發行版。";
"Plist downloaded is nil." = "下載來的更新資訊並非 Plist 檔案。"; "Plist downloaded is nil." = "下載來的更新資訊並非 Plist 檔案。";
@ -17,7 +28,7 @@
"Update Check Failed" = "無法檢查新版"; "Update Check Failed" = "無法檢查新版";
"There may be no internet connection or the server failed to respond.\n\nError message: %@" = "網路連線失敗,或是伺服器沒有回應。\n\n錯誤說明%@"; "There may be no internet connection or the server failed to respond.\n\nError message: %@" = "網路連線失敗,或是伺服器沒有回應。\n\n錯誤說明%@";
"OK" = "確定"; "OK" = "確定";
"Dismiss" = "關閉本視窗"; "Cancel" = "取消";
"New Version Available" = "有新版可下載"; "New Version Available" = "有新版可下載";
"Not Now" = "以後再說"; "Not Now" = "以後再說";
"Visit Website" = "前往網站"; "Visit Website" = "前往網站";

View File

@ -1,5 +1,3 @@
// (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). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

View File

@ -0,0 +1,167 @@
// (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 Cocoa
class ctlClientListMgr: NSWindowController, NSTableViewDelegate, NSTableViewDataSource {
@IBOutlet var tblClients: NSTableView!
@IBOutlet var btnRemoveClient: NSButton!
@IBOutlet var btnAddClient: NSButton!
@IBOutlet var lblClientMgrWindow: NSTextField!
override func windowDidLoad() {
super.windowDidLoad()
localize()
tblClients.delegate = self
tblClients.dataSource = self
tblClients.reloadData()
}
}
// MARK: - Implementations
extension ctlClientListMgr {
func numberOfRows(in _: NSTableView) -> Int {
mgrPrefs.clientsIMKTextInputIncapable.count
}
func callAlert(_ window: NSWindow, title: String, text: String? = nil) {
let alert = NSAlert()
alert.messageText = title
if let text = text {
alert.informativeText = text
}
alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
alert.beginSheetModal(for: window)
}
@IBAction func btnAddClientClicked(_: Any) {
guard let window = window else { return }
let alert = NSAlert()
alert.messageText = NSLocalizedString(
"Please enter the client app bundle identifier(s) you want to register.", comment: ""
)
alert.informativeText = NSLocalizedString(
"One record per line. Use Option+Enter to break lines.\nBlank lines will be dismissed.", comment: ""
)
alert.addButton(withTitle: NSLocalizedString("OK", comment: ""))
alert.addButton(withTitle: NSLocalizedString("Just Select", comment: "") + "")
alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
let maxFloat = CGFloat(Float.greatestFiniteMagnitude)
let scrollview = NSScrollView(frame: NSRect(x: 0, y: 0, width: 370, height: 380))
let contentSize = scrollview.contentSize
scrollview.borderType = .noBorder
scrollview.hasVerticalScroller = true
scrollview.hasHorizontalScroller = true
scrollview.horizontalScroller?.scrollerStyle = .legacy
scrollview.verticalScroller?.scrollerStyle = .legacy
scrollview.autoresizingMask = [.width, .height]
let theTextView = NSTextView(frame: NSRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height))
theTextView.minSize = NSSize(width: 0.0, height: contentSize.height)
theTextView.maxSize = NSSize(width: maxFloat, height: maxFloat)
theTextView.isVerticallyResizable = true
theTextView.isHorizontallyResizable = false
theTextView.autoresizingMask = .width
theTextView.textContainer?.containerSize = NSSize(width: contentSize.width, height: maxFloat)
theTextView.textContainer?.widthTracksTextView = true
scrollview.documentView = theTextView
theTextView.enclosingScrollView?.hasHorizontalScroller = true
theTextView.isHorizontallyResizable = true
theTextView.autoresizingMask = [.width, .height]
theTextView.textContainer?.containerSize = NSSize(width: maxFloat, height: maxFloat)
theTextView.textContainer?.widthTracksTextView = false
alert.accessoryView = scrollview
alert.beginSheetModal(for: window) { result in
switch result {
case .alertFirstButtonReturn:
theTextView.textContainer?.textView?.string.components(separatedBy: "\n").filter { !$0.isEmpty }.forEach {
self.applyNewValue($0)
}
case .alertSecondButtonReturn:
IME.dlgOpenPath.title = NSLocalizedString(
"Choose the target application bundle.", comment: ""
)
IME.dlgOpenPath.showsResizeIndicator = true
IME.dlgOpenPath.showsHiddenFiles = true
IME.dlgOpenPath.canChooseFiles = true
IME.dlgOpenPath.canChooseDirectories = false
IME.dlgOpenPath.beginSheetModal(for: window) { result in
switch result {
case .OK:
guard let url = IME.dlgOpenPath.url else { return }
var title = NSLocalizedString("The selected item is not a valid macOS application bundle.", comment: "")
let text = NSLocalizedString("Please try again.", comment: "")
guard let bundle = Bundle(url: url) else {
self.callAlert(window, title: title, text: text)
return
}
guard let identifier = bundle.bundleIdentifier else {
self.callAlert(window, title: title, text: text)
return
}
if mgrPrefs.clientsIMKTextInputIncapable.contains(identifier) {
title = NSLocalizedString(
"The selected item's identifier is already in the list.", comment: ""
)
self.callAlert(window, title: title)
return
}
self.applyNewValue(identifier)
default: return
}
}
default: return
}
}
}
private func applyNewValue(_ newValue: String) {
guard !newValue.isEmpty else { return }
var arrResult = mgrPrefs.clientsIMKTextInputIncapable
arrResult.append(newValue)
mgrPrefs.clientsIMKTextInputIncapable = arrResult.sorted()
tblClients.reloadData()
btnRemoveClient.isEnabled = (0..<mgrPrefs.clientsIMKTextInputIncapable.count).contains(
tblClients.selectedRow)
}
@IBAction func btnRemoveClientClicked(_: Any) {
if tblClients.selectedRow >= mgrPrefs.clientsIMKTextInputIncapable.count { return }
if tblClients.selectedRow < 0 { return }
let isLastRow: Bool = {
if mgrPrefs.clientsIMKTextInputIncapable.count < 2 { return false }
return tblClients.selectedRow == mgrPrefs.clientsIMKTextInputIncapable.count - 1
}()
mgrPrefs.clientsIMKTextInputIncapable.remove(at: tblClients.selectedRow)
if isLastRow {
tblClients.selectRowIndexes(.init(arrayLiteral: tblClients.selectedRow - 1), byExtendingSelection: false)
}
tblClients.reloadData()
btnRemoveClient.isEnabled = (0..<mgrPrefs.clientsIMKTextInputIncapable.count).contains(tblClients.selectedRow)
}
func tableView(_: NSTableView, objectValueFor _: NSTableColumn?, row: Int) -> Any? {
defer {
self.btnRemoveClient.isEnabled = (0..<mgrPrefs.clientsIMKTextInputIncapable.count).contains(
self.tblClients.selectedRow)
}
return mgrPrefs.clientsIMKTextInputIncapable[row]
}
private func localize() {
guard let window = window else { return }
window.title = NSLocalizedString("Client Manager", comment: "")
lblClientMgrWindow.stringValue = NSLocalizedString(
"Please manage the list of IMKTextInput-incompatible clients here. Clients listed here will trigger vChewing's built-in popup composition buffer window with maximum 20 reading counts holdable.",
comment: ""
)
btnAddClient.title = NSLocalizedString("Add Client", comment: "")
btnRemoveClient.title = NSLocalizedString("Remove Selected", comment: "")
}
}

View File

@ -55,7 +55,7 @@
</textField> </textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8M8-3C-BZO"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8M8-3C-BZO">
<rect key="frame" x="89" y="387" width="431" height="15"/> <rect key="frame" x="89" y="387" width="431" height="15"/>
<textFieldCell key="cell" selectable="YES" title="Placeholder for detailed credits." id="lblCredits"> <textFieldCell key="cell" title="Placeholder for detailed credits." id="lblCredits">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -77,7 +77,7 @@
<constraints> <constraints>
<constraint firstAttribute="width" constant="356" id="B0d-48-3we"/> <constraint firstAttribute="width" constant="356" id="B0d-48-3we"/>
</constraints> </constraints>
<textFieldCell key="cell" selectable="YES" id="lblDisclaimer"> <textFieldCell key="cell" id="lblDisclaimer">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string> <string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>

View File

@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21225" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21225"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="ctlClientListMgr" customModule="vChewing" customModuleProvider="target">
<connections>
<outlet property="btnAddClient" destination="JcI-Ff-tDM" id="XbA-OK-zl8"/>
<outlet property="btnRemoveClient" destination="UNR-wG-8n1" id="vkb-81-1hA"/>
<outlet property="lblClientMgrWindow" destination="3ev-ns-FKY" id="VqL-RC-OdY"/>
<outlet property="tblClients" destination="vIw-vc-WKJ" id="2lw-U5-JAh"/>
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Client Manager" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="F0z-JX-Cv5">
<windowStyleMask key="styleMask" titled="YES" closable="YES" fullSizeContentView="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="664" height="335"/>
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
<view key="contentView" id="se5-gp-TjO" customClass="NSVisualEffectView" customModule="vChewing" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="664" height="335"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="3ev-ns-FKY" userLabel="lblClientMgrWindow">
<rect key="frame" x="18" y="20" width="494" height="46"/>
<constraints>
<constraint firstAttribute="height" constant="46" id="HDu-vv-Kcv"/>
<constraint firstAttribute="width" constant="490" id="LhL-fH-PVL"/>
</constraints>
<textFieldCell key="cell" title="Placeholder for description texts." id="hvd-Wx-n7n">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<scrollView autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MUP-Im-g6c">
<rect key="frame" x="20" y="76" width="624" height="232"/>
<clipView key="contentView" id="wKQ-IV-k62">
<rect key="frame" x="1" y="1" width="622" height="230"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="inset" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" id="vIw-vc-WKJ" userLabel="tblClients">
<rect key="frame" x="0.0" y="0.0" width="622" height="230"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="17" height="0.0"/>
<color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn identifier="AutomaticTableColumnIdentifier.0" width="590" minWidth="40" maxWidth="1000" id="kWw-Lj-EFx">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
</tableHeaderCell>
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="evF-0c-DTr">
<font key="font" metaFont="system" size="20"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
</tableColumn>
</tableColumns>
</tableView>
</subviews>
<nil key="backgroundColor"/>
</clipView>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="6Wq-mB-m8K">
<rect key="frame" x="1" y="215" width="622" height="16"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="rYb-HR-4th">
<rect key="frame" x="224" y="17" width="15" height="102"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="qCN-8Z-3x3">
<rect key="frame" x="518" y="20" width="126" height="46"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JcI-Ff-tDM" userLabel="btnAddClient">
<rect key="frame" x="-7" y="19" width="140" height="32"/>
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7rO-JZ-kgV">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btnAddClientClicked:" target="-2" id="klb-NT-gqr"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UNR-wG-8n1" userLabel="btnRemoveClient">
<rect key="frame" x="-7" y="-7" width="140" height="32"/>
<buttonCell key="cell" type="push" title="Remove" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="wNc-xy-U4i">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="btnRemoveClientClicked:" target="-2" id="VbY-dw-fRP"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="JcI-Ff-tDM" firstAttribute="trailing" secondItem="UNR-wG-8n1" secondAttribute="trailing" id="3Fe-KL-u9x"/>
<constraint firstAttribute="bottom" secondItem="UNR-wG-8n1" secondAttribute="bottom" id="5MS-Xg-KDM"/>
<constraint firstItem="JcI-Ff-tDM" firstAttribute="top" secondItem="qCN-8Z-3x3" secondAttribute="top" id="DZc-Jc-kVr"/>
<constraint firstAttribute="trailing" secondItem="JcI-Ff-tDM" secondAttribute="trailing" id="foA-xu-NF8"/>
<constraint firstItem="JcI-Ff-tDM" firstAttribute="leading" secondItem="UNR-wG-8n1" secondAttribute="leading" id="hOp-FU-UKN"/>
<constraint firstItem="JcI-Ff-tDM" firstAttribute="leading" secondItem="qCN-8Z-3x3" secondAttribute="leading" id="r1x-vo-9qt"/>
</constraints>
</customView>
</subviews>
<constraints>
<constraint firstItem="3ev-ns-FKY" firstAttribute="top" secondItem="MUP-Im-g6c" secondAttribute="bottom" constant="10" id="2tx-uw-Zdh"/>
<constraint firstAttribute="bottom" secondItem="3ev-ns-FKY" secondAttribute="bottom" constant="20" symbolic="YES" id="9KE-bP-0Yi"/>
<constraint firstItem="MUP-Im-g6c" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="27" id="BkF-ED-Uva"/>
<constraint firstAttribute="trailing" secondItem="MUP-Im-g6c" secondAttribute="trailing" constant="20" symbolic="YES" id="E0U-Vh-g3t"/>
<constraint firstItem="MUP-Im-g6c" firstAttribute="trailing" secondItem="qCN-8Z-3x3" secondAttribute="trailing" id="TqZ-q6-quu"/>
<constraint firstItem="MUP-Im-g6c" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="20" symbolic="YES" id="WXt-cJ-HaW"/>
<constraint firstItem="3ev-ns-FKY" firstAttribute="top" secondItem="qCN-8Z-3x3" secondAttribute="top" id="b4O-RW-K56"/>
<constraint firstItem="MUP-Im-g6c" firstAttribute="leading" secondItem="3ev-ns-FKY" secondAttribute="leading" id="g8i-I5-2Dw"/>
<constraint firstItem="3ev-ns-FKY" firstAttribute="bottom" secondItem="qCN-8Z-3x3" secondAttribute="bottom" id="ktC-2I-aWz"/>
<constraint firstItem="qCN-8Z-3x3" firstAttribute="leading" secondItem="3ev-ns-FKY" secondAttribute="trailing" constant="8" symbolic="YES" id="opE-OC-8Dh"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
</connections>
<point key="canvasLocation" x="231" y="176.5"/>
</window>
</objects>
</document>

View File

@ -3,9 +3,9 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.5.0</string> <string>2.6.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2500</string> <string>2600</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

@ -32,6 +32,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
ctlAboutWindowInstance?.window?.center() ctlAboutWindowInstance?.window?.center()
ctlAboutWindowInstance?.window?.orderFrontRegardless() // ctlAboutWindowInstance?.window?.orderFrontRegardless() //
ctlAboutWindowInstance?.window?.level = .statusBar ctlAboutWindowInstance?.window?.level = .statusBar
ctlAboutWindowInstance?.window?.titlebarAppearsTransparent = true
} }
// Call the New About Window // Call the New About Window

View File

@ -55,7 +55,7 @@
</textField> </textField>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8M8-3C-BZO"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" translatesAutoresizingMaskIntoConstraints="NO" id="8M8-3C-BZO">
<rect key="frame" x="89" y="372" width="431" height="30"/> <rect key="frame" x="89" y="372" width="431" height="30"/>
<textFieldCell key="cell" selectable="YES" id="lblCredits"> <textFieldCell key="cell" id="lblCredits">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<string key="title">vChewing Phrase Editor developed by Shiki Suen. <string key="title">vChewing Phrase Editor developed by Shiki Suen.
vChewing Phrase Database Maintained by Shiki Suen.</string> vChewing Phrase Database Maintained by Shiki Suen.</string>
@ -79,7 +79,7 @@ vChewing Phrase Database Maintained by Shiki Suen.</string>
<constraints> <constraints>
<constraint firstAttribute="width" constant="356" id="B0d-48-3we"/> <constraint firstAttribute="width" constant="356" id="B0d-48-3we"/>
</constraints> </constraints>
<textFieldCell key="cell" selectable="YES" id="lblDisclaimer"> <textFieldCell key="cell" id="lblDisclaimer">
<font key="font" size="12" name="Tahoma"/> <font key="font" size="12" name="Tahoma"/>
<string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string> <string key="title">DISCLAIMER: The vChewing project, having no relationship of cooperation or affiliation with the OpenVanilla project, is not responsible for the phrase database shipped in the original McBopomofo project. Certain geopolitical and ideological contents, which are potentially harmful to the global spread of this software, are not included in vChewing official phrase database.</string>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>

View File

@ -1,5 +1,3 @@
// (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). // (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ==================== // ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT) // This code is released under the MIT license (SPDX-License-Identifier: MIT)

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>2.5.0</string> <string>2.6.0</string>
</dict> </dict>
<key>TYPE</key> <key>TYPE</key>
<integer>0</integer> <integer>0</integer>

View File

@ -9,6 +9,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; }; 5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; };
5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; }; 5B0AF8B527B2C8290096FE54 /* StringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */; };
5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */; };
5B0EF55F28CDBF8E00F8F7CE /* ctlClientListMgr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0EF55E28CDBF8E00F8F7CE /* ctlClientListMgr.swift */; };
5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; }; 5B11328927B94CFB00E58451 /* AppleKeyboardConverter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */; };
5B16B84C28C9A89000ABA692 /* FolderMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B16B84B28C9A89000ABA692 /* FolderMonitor.swift */; }; 5B16B84C28C9A89000ABA692 /* FolderMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B16B84B28C9A89000ABA692 /* FolderMonitor.swift */; };
5B175FFB28C5CDDC0078D1B4 /* IMKHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */; }; 5B175FFB28C5CDDC0078D1B4 /* IMKHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */; };
@ -39,6 +41,7 @@
5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; }; 5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; };
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */; }; 5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */; };
5B62A34A27AE7CD900A19448 /* NotifierController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34527AE7CD900A19448 /* NotifierController.swift */; }; 5B62A34A27AE7CD900A19448 /* NotifierController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34527AE7CD900A19448 /* NotifierController.swift */; };
5B630A3C28CC97020010D076 /* ctlPopupCompositionBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B630A3B28CC97020010D076 /* ctlPopupCompositionBuffer.swift */; };
5B6C141228A9D4B30098ADF8 /* ctlInputMethod_Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_Common.swift */; }; 5B6C141228A9D4B30098ADF8 /* ctlInputMethod_Common.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_Common.swift */; };
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; }; 5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; }; 5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B782EC3280C243C007276DE /* KeyHandler_HandleCandidate.swift */; };
@ -210,6 +213,8 @@
5B09307B28B6FC410021F8C5 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = ja; path = ja.lproj/shortcuts.html; sourceTree = "<group>"; }; 5B09307B28B6FC410021F8C5 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = ja; path = ja.lproj/shortcuts.html; sourceTree = "<group>"; };
5B0AF8B427B2C8290096FE54 /* StringExtension.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = StringExtension.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B0AF8B427B2C8290096FE54 /* StringExtension.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = StringExtension.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = frmClientListMgr.xib; sourceTree = "<group>"; };
5B0EF55E28CDBF8E00F8F7CE /* ctlClientListMgr.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ctlClientListMgr.swift; sourceTree = "<group>"; };
5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppleKeyboardConverter.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B11328827B94CFB00E58451 /* AppleKeyboardConverter.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = AppleKeyboardConverter.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B16B84B28C9A89000ABA692 /* FolderMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderMonitor.swift; sourceTree = "<group>"; }; 5B16B84B28C9A89000ABA692 /* FolderMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FolderMonitor.swift; sourceTree = "<group>"; };
5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IMKHelper.swift; sourceTree = "<group>"; }; 5B175FFA28C5CDDC0078D1B4 /* IMKHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IMKHelper.swift; sourceTree = "<group>"; };
@ -253,6 +258,7 @@
5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlAboutWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlAboutWindow.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B62A34027AE7CD900A19448 /* ctlCandidate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlCandidate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlCandidate.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B62A34527AE7CD900A19448 /* NotifierController.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = NotifierController.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; }; 5B62A34527AE7CD900A19448 /* NotifierController.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = NotifierController.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
5B630A3B28CC97020010D076 /* ctlPopupCompositionBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlPopupCompositionBuffer.swift; sourceTree = "<group>"; };
5B65B919284D0185007C558B /* README-CHT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHT.md"; sourceTree = "<group>"; }; 5B65B919284D0185007C558B /* README-CHT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHT.md"; sourceTree = "<group>"; };
5B6C141128A9D4B30098ADF8 /* ctlInputMethod_Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_Common.swift; sourceTree = "<group>"; }; 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_Common.swift; sourceTree = "<group>"; };
5B73FB5427B2BD6900E9BF49 /* PhraseEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PhraseEditor-Info.plist"; path = "UserPhraseEditor/PhraseEditor-Info.plist"; sourceTree = SOURCE_ROOT; }; 5B73FB5427B2BD6900E9BF49 /* PhraseEditor-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "PhraseEditor-Info.plist"; path = "UserPhraseEditor/PhraseEditor-Info.plist"; sourceTree = SOURCE_ROOT; };
@ -581,6 +587,7 @@
children = ( children = (
5B62A33E27AE7CD900A19448 /* CandidateUI */, 5B62A33E27AE7CD900A19448 /* CandidateUI */,
5B62A34427AE7CD900A19448 /* NotifierUI */, 5B62A34427AE7CD900A19448 /* NotifierUI */,
5B630A3A28CC96D80010D076 /* PopupCompositionBufferUI */,
5BA9FD0927FED9F3002DE248 /* PrefUI */, 5BA9FD0927FED9F3002DE248 /* PrefUI */,
5B62A34227AE7CD900A19448 /* TooltipUI */, 5B62A34227AE7CD900A19448 /* TooltipUI */,
); );
@ -591,6 +598,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */, 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */,
5B0EF55E28CDBF8E00F8F7CE /* ctlClientListMgr.swift */,
D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */, D47F7DCD278BFB57002F9DD7 /* ctlPrefWindow.swift */,
); );
path = WindowControllers; path = WindowControllers;
@ -599,6 +607,7 @@
5B62A33B27AE7C7F00A19448 /* WindowNIBs */ = { 5B62A33B27AE7C7F00A19448 /* WindowNIBs */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */,
5BBBB76927AED5DB0023B93A /* frmAboutWindow.xib */, 5BBBB76927AED5DB0023B93A /* frmAboutWindow.xib */,
5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */, 5B7BC4AE27AFFBE800F66C24 /* frmPrefWindow.xib */,
6A187E2816004C5900466B2E /* MainMenu.xib */, 6A187E2816004C5900466B2E /* MainMenu.xib */,
@ -645,6 +654,14 @@
name = Data; name = Data;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
5B630A3A28CC96D80010D076 /* PopupCompositionBufferUI */ = {
isa = PBXGroup;
children = (
5B630A3B28CC97020010D076 /* ctlPopupCompositionBuffer.swift */,
);
path = PopupCompositionBufferUI;
sourceTree = "<group>";
};
5B84579B2871AD2200C93B01 /* HotenkaChineseConverter */ = { 5B84579B2871AD2200C93B01 /* HotenkaChineseConverter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1068,6 +1085,7 @@
D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */, D4E33D8A27A838CF006DB1CF /* Localizable.strings in Resources */,
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */, 5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */,
5B7DA80328BF6BC600D7B2AD /* fixinstall.sh in Resources */, 5B7DA80328BF6BC600D7B2AD /* fixinstall.sh in Resources */,
5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */,
5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */, 5BDCBB2E27B4E67A00D0CC59 /* vChewingPhraseEditor.app in Resources */,
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */, 5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */,
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */, 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
@ -1214,6 +1232,7 @@
5B5F8AEE28C8826D007C11F1 /* ctlTooltip.swift in Sources */, 5B5F8AEE28C8826D007C11F1 /* ctlTooltip.swift in Sources */,
5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */, 5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */,
5B2170E7289FACAD00BE7304 /* 1_Compositor.swift in Sources */, 5B2170E7289FACAD00BE7304 /* 1_Compositor.swift in Sources */,
5B0EF55F28CDBF8E00F8F7CE /* ctlClientListMgr.swift in Sources */,
5B21177028753B9D000443A9 /* ctlInputMethod_Delegates.swift in Sources */, 5B21177028753B9D000443A9 /* ctlInputMethod_Delegates.swift in Sources */,
5B21176E28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift in Sources */, 5B21176E28753B35000443A9 /* ctlInputMethod_HandleDisplay.swift in Sources */,
5B84579F2871AD2200C93B01 /* HotenkaChineseConverter.swift in Sources */, 5B84579F2871AD2200C93B01 /* HotenkaChineseConverter.swift in Sources */,
@ -1268,6 +1287,7 @@
5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */, 5BA9FD1327FEDB6B002DE248 /* suiPrefPaneDictionary.swift in Sources */,
5B2170E8289FACAD00BE7304 /* 5_Vertex.swift in Sources */, 5B2170E8289FACAD00BE7304 /* 5_Vertex.swift in Sources */,
5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */, 5BBBB77A27AEDC690023B93A /* clsSFX.swift in Sources */,
5B630A3C28CC97020010D076 /* ctlPopupCompositionBuffer.swift in Sources */,
5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */, 5BA9FD4727FEF3C9002DE248 /* PreferencesStyleController.swift in Sources */,
5B949BDB2816DDBC00D87B5D /* LMConsolidator.swift in Sources */, 5B949BDB2816DDBC00D87B5D /* LMConsolidator.swift in Sources */,
5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */, 5BFDF011289635C100417BBC /* ctlCandidateIMK.swift in Sources */,
@ -1463,7 +1483,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
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 = (
@ -1473,7 +1493,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 = 2.5.0; MARKETING_VERSION = 2.6.0;
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;
@ -1502,13 +1522,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
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 = 2.5.0; MARKETING_VERSION = 2.6.0;
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;
@ -1540,7 +1560,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1562,7 +1582,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
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;
@ -1592,7 +1612,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -1610,7 +1630,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
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;
@ -1726,7 +1746,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1755,7 +1775,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
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)";
@ -1785,7 +1805,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1808,7 +1828,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
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 = "";
@ -1832,7 +1852,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1853,7 +1873,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
@ -1876,7 +1896,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 = 2500; CURRENT_PROJECT_VERSION = 2600;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1891,7 +1911,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/../Frameworks", "@executable_path/../Frameworks",
); );
MARKETING_VERSION = 2.5.0; MARKETING_VERSION = 2.6.0;
PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller; PRODUCT_BUNDLE_IDENTIFIER = org.atelierInmu.vChewing.vChewingInstaller;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";