NotifierUI // Refactor into a standalone package.

This commit is contained in:
ShikiSuen 2022-09-23 18:34:33 +08:00
parent d8fb9aee1d
commit 1f5481a8d4
9 changed files with 227 additions and 254 deletions

View File

@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View File

@ -0,0 +1,22 @@
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "NotifierUI",
platforms: [
.macOS(.v10_11)
],
products: [
.library(
name: "NotifierUI",
targets: ["NotifierUI"]
)
],
dependencies: [],
targets: [
.target(
name: "NotifierUI",
dependencies: []
)
]
)

View File

@ -0,0 +1,13 @@
# NotifierUI
威注音的飄雲通知視窗。
```
// (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.
```

View File

@ -0,0 +1,155 @@
// (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 Notifier: NSWindowController {
public static func notify(message: String) {
Self.message = message
}
static var message: String = "" {
didSet {
if !Self.message.isEmpty {
Self.message = Notifier(message).blankValue
}
}
}
// MARK: - Private Declarations
private static var instanceStack: [Notifier] = []
private let blankValue = ""
@discardableResult private init(_ message: String) {
let rawMessage = message.replacingOccurrences(of: "\n", with: "")
guard let screenRect = NSScreen.main?.visibleFrame, !rawMessage.isEmpty else {
super.init(window: nil)
return
}
let kLargeFontSize: Double = 17
let kSmallFontSize: Double = 15
let messageArray = message.components(separatedBy: "\n")
let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .center
let attrTitle: [NSAttributedString.Key: AnyObject] = [
.foregroundColor: NSColor.controlTextColor,
.font: NSFont.boldSystemFont(ofSize: kLargeFontSize),
.paragraphStyle: paraStyle,
]
let attrString = NSMutableAttributedString(string: messageArray[0], attributes: attrTitle)
let attrAlt: [NSAttributedString.Key: AnyObject] = [
.foregroundColor: NSColor.secondaryLabelColor,
.font: NSFont.systemFont(ofSize: kSmallFontSize),
.paragraphStyle: paraStyle,
]
let additionalString = messageArray.count > 1 ? "\n\(messageArray[1])" : ""
let attrStringAlt = NSMutableAttributedString(string: additionalString, attributes: attrAlt)
attrString.insert(attrStringAlt, at: attrString.length)
let textRect: NSRect = attrString.boundingRect(
with: NSSize(width: 1600.0, height: 1600.0), options: [.usesLineFragmentOrigin]
)
let windowWidth = Double(4) * kLargeFontSize + textRect.width
let contentRect = NSRect(x: 0, y: 0, width: windowWidth, height: 60.0)
var windowRect = contentRect
windowRect.origin.x = screenRect.maxX - windowRect.width - 10
windowRect.origin.y = screenRect.maxY - windowRect.height - 10
let styleMask: NSWindow.StyleMask = [.borderless]
let transparentVisualEffect = NSVisualEffectView()
transparentVisualEffect.blendingMode = .behindWindow
transparentVisualEffect.state = .active
let theWindow = NSWindow(
contentRect: windowRect, styleMask: styleMask, backing: .buffered, defer: false
)
theWindow.contentView = transparentVisualEffect
theWindow.isMovableByWindowBackground = true
theWindow.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel))
theWindow.hasShadow = true
theWindow.backgroundColor = .textBackgroundColor
theWindow.title = ""
theWindow.titlebarAppearsTransparent = true
theWindow.titleVisibility = .hidden
theWindow.showsToolbarButton = false
theWindow.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
theWindow.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
theWindow.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
theWindow.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
theWindow.isReleasedWhenClosed = true
theWindow.isMovable = false
let lblMessage = NSTextField()
lblMessage.attributedStringValue = attrString
lblMessage.drawsBackground = false
lblMessage.font = .boldSystemFont(ofSize: NSFont.systemFontSize(for: .regular))
lblMessage.frame = contentRect
lblMessage.isBezeled = false
lblMessage.isEditable = false
lblMessage.isSelectable = false
lblMessage.textColor = .controlTextColor
theWindow.contentView?.addSubview(lblMessage)
let x = lblMessage.frame.origin.x
let y = ((theWindow.frame.height) - textRect.height) / 1.9
let newFrame = NSRect(x: x, y: y, width: theWindow.frame.width, height: textRect.height)
lblMessage.frame = newFrame
super.init(window: theWindow)
display()
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override public func close() {
super.close()
}
}
// MARK: - Private Functions
extension Notifier {
private func shiftExistingWindowPositions() {
guard let window = window, !Self.instanceStack.isEmpty else { return }
for theInstanceWindow in Self.instanceStack.compactMap(\.window) {
var theOrigin = theInstanceWindow.frame
theOrigin.origin.y -= (10 + window.frame.height)
theInstanceWindow.setFrame(theOrigin, display: true)
}
}
private func fadeIn() {
guard let window = window else { return }
let afterRect = window.frame
var beforeRect = afterRect
beforeRect.origin.x -= 20
window.setFrame(beforeRect, display: true)
window.orderFront(self)
window.setFrame(afterRect, display: true, animate: true)
}
private func display() {
let existingInstanceArray = Self.instanceStack.compactMap(\.window)
if !existingInstanceArray.isEmpty {
existingInstanceArray.forEach { $0.alphaValue *= 0.5 }
}
shiftExistingWindowPositions()
fadeIn()
Self.instanceStack.insert(self, at: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.close()
Self.instanceStack.removeAll(where: { $0.window == nil })
}
}
}

View File

@ -9,6 +9,7 @@
import BookmarkManager
import LangModelAssembly
import Megrez
import NotifierUI
import Shared
/// 使
@ -98,7 +99,7 @@ public enum LMMgr {
}
if !Self.lmCHT.isLanguageModelLoaded {
showFinishNotification = true
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Loading CHT Core Dict...", comment: "")
)
group.enter()
@ -109,7 +110,7 @@ public enum LMMgr {
}
if !Self.lmCHS.isLanguageModelLoaded {
showFinishNotification = true
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Loading CHS Core Dict...", comment: "")
)
group.enter()
@ -120,7 +121,7 @@ public enum LMMgr {
}
group.notify(queue: DispatchQueue.main) {
if showFinishNotification {
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Core Dict loading complete.", comment: "")
)
}
@ -162,7 +163,7 @@ public enum LMMgr {
case .imeModeCHS:
if !Self.lmCHS.isLanguageModelLoaded {
showFinishNotification = true
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Loading CHS Core Dict...", comment: "")
)
group.enter()
@ -174,7 +175,7 @@ public enum LMMgr {
case .imeModeCHT:
if !Self.lmCHT.isLanguageModelLoaded {
showFinishNotification = true
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Loading CHT Core Dict...", comment: "")
)
group.enter()
@ -187,7 +188,7 @@ public enum LMMgr {
}
group.notify(queue: DispatchQueue.main) {
if showFinishNotification {
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Core Dict loading complete.", comment: "")
)
}

View File

@ -1,226 +0,0 @@
// (c) 2021 and onwards Weizhong Yang (MIT License).
// All possible vChewing-specific modifications are of:
// (c) 2021 and onwards The vChewing Project (MIT-NTL License).
// ====================
// This code is released under the MIT license (SPDX-License-Identifier: MIT)
// ... with NTL restriction stating that:
// No trademark license is granted to use the trade names, trademarks, service
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
private protocol NotifierWindowDelegate: AnyObject {
func windowDidBecomeClicked(_ window: NotifierWindow)
}
private class NotifierWindow: NSWindow {
weak var clickDelegate: NotifierWindowDelegate?
override func mouseDown(with _: NSEvent) {
clickDelegate?.windowDidBecomeClicked(self)
}
}
private let kWindowWidth: CGFloat = 213.0
private let kWindowHeight: CGFloat = 60.0
public class NotifierController: NSWindowController, NotifierWindowDelegate {
static var message: String = "" {
didSet {
if !Self.message.isEmpty {
NotifierController.initiateWithNoStay(message: message)
Self.message = ""
}
}
}
private var messageTextField: NSTextField
private var message: String = "" {
didSet {
let paraStyle = NSMutableParagraphStyle()
paraStyle.setParagraphStyle(NSParagraphStyle.default)
paraStyle.alignment = .center
let attr: [NSAttributedString.Key: AnyObject] = [
.foregroundColor: foregroundColor,
.font: NSFont.boldSystemFont(ofSize: NSFont.systemFontSize(for: .regular)),
.paragraphStyle: paraStyle,
]
let attrString = NSAttributedString(string: message, attributes: attr)
messageTextField.attributedStringValue = attrString
let width = window?.frame.width ?? kWindowWidth
let rect = attrString.boundingRect(
with: NSSize(width: width, height: 1600), options: .usesLineFragmentOrigin
)
let height = rect.height
let x = messageTextField.frame.origin.x
let y = ((window?.frame.height ?? kWindowHeight) - height) / 2
let newFrame = NSRect(x: x, y: y, width: width, height: height)
messageTextField.frame = newFrame
}
}
private var shouldStay = false
private var backgroundColor: NSColor = .textBackgroundColor {
didSet {
window?.backgroundColor = backgroundColor
}
}
private var foregroundColor: NSColor = .controlTextColor {
didSet {
messageTextField.textColor = foregroundColor
}
}
private var waitTimer: Timer?
private var fadeTimer: Timer?
private static var instanceCount = 0
private static var lastLocation = NSPoint.zero
private static func initiateWithNoStay(message: String) {
let controller = NotifierController()
controller.message = message
controller.show()
}
public static func notify(message: String) {
Self.message = message
}
public static func notify(message: String, stay: Bool) {
let controller = NotifierController()
controller.message = message
controller.shouldStay = stay
controller.show()
}
private static func increaseInstanceCount() {
instanceCount += 1
}
private static func decreaseInstanceCount() {
instanceCount -= 1
if instanceCount < 0 {
instanceCount = 0
}
}
private init() {
let screenRect = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
let contentRect = NSRect(x: 0, y: 0, width: kWindowWidth, height: kWindowHeight)
var windowRect = contentRect
windowRect.origin.x = screenRect.maxX - windowRect.width - 10
windowRect.origin.y = screenRect.maxY - windowRect.height - 10
let styleMask: NSWindow.StyleMask = [.fullSizeContentView, .titled]
let transparentVisualEffect = NSVisualEffectView()
transparentVisualEffect.blendingMode = .behindWindow
transparentVisualEffect.state = .active
let panel = NotifierWindow(
contentRect: windowRect, styleMask: styleMask, backing: .buffered, defer: false
)
panel.contentView = transparentVisualEffect
panel.isMovableByWindowBackground = true
panel.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel))
panel.hasShadow = true
panel.backgroundColor = backgroundColor
panel.title = ""
panel.titlebarAppearsTransparent = true
panel.titleVisibility = .hidden
panel.showsToolbarButton = false
panel.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
panel.standardWindowButton(NSWindow.ButtonType.miniaturizeButton)?.isHidden = true
panel.standardWindowButton(NSWindow.ButtonType.closeButton)?.isHidden = true
panel.standardWindowButton(NSWindow.ButtonType.zoomButton)?.isHidden = true
messageTextField = NSTextField()
messageTextField.frame = contentRect
messageTextField.isEditable = false
messageTextField.isSelectable = false
messageTextField.isBezeled = false
messageTextField.textColor = foregroundColor
messageTextField.drawsBackground = false
messageTextField.font = .boldSystemFont(ofSize: NSFont.systemFontSize(for: .regular))
panel.contentView?.addSubview(messageTextField)
super.init(window: panel)
panel.clickDelegate = self
}
@available(*, unavailable)
required init?(coder _: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func show() {
func setStartLocation() {
if Self.instanceCount == 0 {
return
}
let lastLocation = Self.lastLocation
let screenRect = NSScreen.main?.visibleFrame ?? NSRect.seniorTheBeast
var windowRect = window?.frame ?? NSRect.seniorTheBeast
windowRect.origin.x = lastLocation.x
windowRect.origin.y = lastLocation.y - 10 - windowRect.height
if windowRect.origin.y < screenRect.minY {
return
}
window?.setFrame(windowRect, display: true)
}
func moveIn() {
let afterRect = window?.frame ?? NSRect.seniorTheBeast
Self.lastLocation = afterRect.origin
var beforeRect = afterRect
beforeRect.origin.y += 10
window?.setFrame(beforeRect, display: true)
window?.orderFront(self)
window?.setFrame(afterRect, display: true, animate: true)
}
setStartLocation()
moveIn()
Self.increaseInstanceCount()
waitTimer = Timer.scheduledTimer(
timeInterval: shouldStay ? 5 : 1, target: self, selector: #selector(fadeOut),
userInfo: nil,
repeats: false
)
}
@objc private func doFadeOut(_: Timer) {
let opacity = window?.alphaValue ?? 0
if opacity <= 0 {
close()
} else {
window?.alphaValue = opacity - 0.2
}
}
@objc private func fadeOut() {
waitTimer?.invalidate()
waitTimer = nil
Self.decreaseInstanceCount()
fadeTimer = Timer.scheduledTimer(
timeInterval: 0.01, target: self, selector: #selector(doFadeOut(_:)), userInfo: nil,
repeats: true
)
}
override public func close() {
waitTimer?.invalidate()
waitTimer = nil
fadeTimer?.invalidate()
fadeTimer = nil
super.close()
}
fileprivate func windowDidBecomeClicked(_: NotifierWindow) {
fadeOut()
}
}

View File

@ -9,6 +9,7 @@
// requirements defined in MIT License.
import IMKUtils
import NotifierUI
import Shared
import ShiftKeyUpChecker
import Tekkon
@ -272,7 +273,7 @@ class ctlInputMethod: IMKInputController {
if #available(macOS 10.15, *) {
if Self.theShiftKeyDetector.check(event), !PrefMgr.shared.disableShiftTogglingAlphanumericalMode {
if !shouldUseShiftToggleHandle || (!rencentKeyHandledByKeyHandlerEtc && shouldUseShiftToggleHandle) {
NotifierController.notify(
Notifier.notify(
message: isASCIIMode.toggled()
? NSLocalizedString("Alphanumerical Input Mode", comment: "")
: NSLocalizedString("Chinese Input Mode", comment: "")

View File

@ -8,6 +8,7 @@
// marks, or product names of Contributor, except as required to fulfill notice
// requirements defined in MIT License.
import NotifierUI
import Preferences
extension Bool {
@ -223,7 +224,7 @@ extension ctlInputMethod {
@objc func toggleSCPCTypingMode(_: Any? = nil) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Per-Char Select Mode", comment: "") + "\n"
+ (PrefMgr.shared.useSCPCTypingMode.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -233,7 +234,7 @@ extension ctlInputMethod {
@objc func toggleChineseConverter(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Force KangXi Writing", comment: "") + "\n"
+ (PrefMgr.shared.chineseConversionEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -243,7 +244,7 @@ extension ctlInputMethod {
@objc func toggleShiftJISShinjitaiOutput(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("JIS Shinjitai Output", comment: "") + "\n"
+ (PrefMgr.shared.shiftJISShinjitaiOutputEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -253,7 +254,7 @@ extension ctlInputMethod {
@objc func toggleCurrencyNumerals(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Currency Numeral Output", comment: "") + "\n"
+ (PrefMgr.shared.currencyNumeralsEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -263,7 +264,7 @@ extension ctlInputMethod {
@objc func toggleHalfWidthPunctuation(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Half-Width Punctuation Mode", comment: "") + "\n"
+ (PrefMgr.shared.halfWidthPunctuationEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -273,7 +274,7 @@ extension ctlInputMethod {
@objc func toggleCNS11643Enabled(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("CNS11643 Mode", comment: "") + "\n"
+ (PrefMgr.shared.cns11643Enabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -283,7 +284,7 @@ extension ctlInputMethod {
@objc func toggleSymbolEnabled(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Symbol & Emoji Input", comment: "") + "\n"
+ (PrefMgr.shared.symbolInputEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -293,7 +294,7 @@ extension ctlInputMethod {
@objc func toggleAssociatedPhrasesEnabled(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Per-Char Associated Phrases", comment: "") + "\n"
+ (PrefMgr.shared.associatedPhrasesEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")
@ -303,7 +304,7 @@ extension ctlInputMethod {
@objc func togglePhraseReplacement(_: Any?) {
resetKeyHandler()
NotifierController.notify(
Notifier.notify(
message: NSLocalizedString("Use Phrase Replacement", comment: "") + "\n"
+ (PrefMgr.shared.phraseReplacementEnabled.toggled()
? NSLocalizedString("NotificationSwitchON", comment: "")

View File

@ -21,7 +21,6 @@
5B5F8AEE28C8826D007C11F1 /* ctlTooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F8AED28C8826D007C11F1 /* ctlTooltip.swift */; };
5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; };
5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34027AE7CD900A19448 /* ctlCandidate.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_HandleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_HandleEvent.swift */; };
5B73FB5E27B2BE1300E9BF49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 5B73FB6027B2BE1300E9BF49 /* InfoPlist.strings */; };
@ -58,6 +57,7 @@
5BC447A02865686500EDC323 /* data-symbols.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71E283B4AEA0078EB25 /* data-symbols.plist */; };
5BC447A12865686500EDC323 /* data-zhuyinwen.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BEDB71F283B4AEA0078EB25 /* data-zhuyinwen.plist */; };
5BC447A628656A1900EDC323 /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC447A228656A1900EDC323 /* Placeholder.swift */; };
5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */ = {isa = PBXBuildFile; productRef = 5BC5E01D28DDE4770094E427 /* NotifierUI */; };
5BCCAFF828DB19A300AB1B27 /* PrefMgr_Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BCCAFF728DB19A300AB1B27 /* PrefMgr_Extension.swift */; };
5BD0113D2818543900609769 /* KeyHandler_Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BD0113C2818543900609769 /* KeyHandler_Core.swift */; };
5BD05BCA27B2A43D004C4F1D /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6A2E40F5253A69DA00D1AE1D /* Images.xcassets */; };
@ -206,7 +206,6 @@
5B5F8AED28C8826D007C11F1 /* ctlTooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlTooltip.swift; sourceTree = "<group>"; };
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; };
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.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
5B6C141128A9D4B30098ADF8 /* ctlInputMethod_HandleEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_HandleEvent.swift; sourceTree = "<group>"; };
@ -246,6 +245,7 @@
5BC2652127E04B7B00700291 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = uninstall.sh; sourceTree = "<group>"; };
5BC447A228656A1900EDC323 /* Placeholder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Placeholder.swift; sourceTree = "<group>"; };
5BC447AB2865BEF500EDC323 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; path = AUTHORS; sourceTree = "<group>"; };
5BC5E01C28DDE4270094E427 /* vChewing_NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_NotifierUI; path = Packages/vChewing_NotifierUI; sourceTree = "<group>"; };
5BCCAFF728DB19A300AB1B27 /* PrefMgr_Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefMgr_Extension.swift; sourceTree = "<group>"; };
5BD0113C2818543900609769 /* KeyHandler_Core.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = KeyHandler_Core.swift; sourceTree = "<group>"; usesTabs = 0; };
5BD05BB827B2A429004C4F1D /* vChewingPhraseEditor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = vChewingPhraseEditor.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -353,6 +353,7 @@
5B40113928D7050D00A9D4CB /* Shared in Frameworks */,
5BFC63C628D48806004A77B7 /* NSAttributedTextView in Frameworks */,
5BDB7A3B28D4824A001AC277 /* FolderMonitor in Frameworks */,
5BC5E01E28DDE4770094E427 /* NotifierUI in Frameworks */,
5B40113C28D71C0100A9D4CB /* Uninstaller in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -434,7 +435,6 @@
isa = PBXGroup;
children = (
5B62A33E27AE7CD900A19448 /* CandidateUI */,
5B62A34427AE7CD900A19448 /* NotifierUI */,
5B630A3A28CC96D80010D076 /* PopupCompositionBufferUI */,
5BA9FD0927FED9F3002DE248 /* PrefUI */,
5B62A34227AE7CD900A19448 /* TooltipUI */,
@ -481,14 +481,6 @@
path = TooltipUI;
sourceTree = "<group>";
};
5B62A34427AE7CD900A19448 /* NotifierUI */ = {
isa = PBXGroup;
children = (
5B62A34527AE7CD900A19448 /* NotifierController.swift */,
);
path = NotifierUI;
sourceTree = "<group>";
};
5B62A35027AE7F6600A19448 /* Data */ = {
isa = PBXGroup;
children = (
@ -595,6 +587,7 @@
5BFC63C728D49511004A77B7 /* vChewing_IMKUtils */,
5BFC63CD28D4AC98004A77B7 /* vChewing_LangModelAssembly */,
5BDB7A3328D47587001AC277 /* vChewing_Megrez */,
5BC5E01C28DDE4270094E427 /* vChewing_NotifierUI */,
5B98114628D6198000CBC605 /* vChewing_PinyinPhonaConverter */,
5B963C9E28D5C14600DCEE88 /* vChewing_Shared */,
5B963CA128D5C22D00DCEE88 /* vChewing_SwiftExtension */,
@ -795,6 +788,7 @@
5B98114728D6198700CBC605 /* PinyinPhonaConverter */,
5B40113828D7050D00A9D4CB /* Shared */,
5B40113B28D71C0100A9D4CB /* Uninstaller */,
5BC5E01D28DDE4770094E427 /* NotifierUI */,
);
productName = vChewing;
productReference = 6A0D4EA215FC0D2D00ABF4B3 /* vChewing.app */;
@ -1079,7 +1073,6 @@
D47F7DCE278BFB57002F9DD7 /* ctlPrefWindow.swift in Sources */,
5BD0113D2818543900609769 /* KeyHandler_Core.swift in Sources */,
5BF56F9A28C39D1800DD6839 /* IMEStateData.swift in Sources */,
5B62A34A27AE7CD900A19448 /* NotifierController.swift in Sources */,
5B21176C287539BB000443A9 /* ctlInputMethod_HandleStates.swift in Sources */,
5BAEFAD028012565001F42C9 /* LMMgr.swift in Sources */,
5B782EC4280C243C007276DE /* KeyHandler_HandleCandidate.swift in Sources */,
@ -1791,6 +1784,10 @@
isa = XCSwiftPackageProductDependency;
productName = PinyinPhonaConverter;
};
5BC5E01D28DDE4770094E427 /* NotifierUI */ = {
isa = XCSwiftPackageProductDependency;
productName = NotifierUI;
};
5BDB7A3828D4824A001AC277 /* BookmarkManager */ = {
isa = XCSwiftPackageProductDependency;
productName = BookmarkManager;