From 1f5481a8d4c12d2f4ac75b6a90bc584706fd5a0e Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Fri, 23 Sep 2022 18:34:33 +0800 Subject: [PATCH] NotifierUI // Refactor into a standalone package. --- Packages/vChewing_NotifierUI/.gitignore | 9 + Packages/vChewing_NotifierUI/Package.swift | 22 ++ Packages/vChewing_NotifierUI/README.md | 13 + .../Sources/NotifierUI/NotifierUI.swift | 155 ++++++++++++ Source/Modules/LMMgr.swift | 13 +- .../NotifierUI/NotifierController.swift | 226 ------------------ Source/Modules/ctlInputMethod_Core.swift | 3 +- Source/Modules/ctlInputMethod_Menu.swift | 19 +- vChewing.xcodeproj/project.pbxproj | 21 +- 9 files changed, 227 insertions(+), 254 deletions(-) create mode 100644 Packages/vChewing_NotifierUI/.gitignore create mode 100644 Packages/vChewing_NotifierUI/Package.swift create mode 100644 Packages/vChewing_NotifierUI/README.md create mode 100644 Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift delete mode 100644 Source/Modules/UIModules/NotifierUI/NotifierController.swift diff --git a/Packages/vChewing_NotifierUI/.gitignore b/Packages/vChewing_NotifierUI/.gitignore new file mode 100644 index 00000000..3b298120 --- /dev/null +++ b/Packages/vChewing_NotifierUI/.gitignore @@ -0,0 +1,9 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/config/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/Packages/vChewing_NotifierUI/Package.swift b/Packages/vChewing_NotifierUI/Package.swift new file mode 100644 index 00000000..45cda7d5 --- /dev/null +++ b/Packages/vChewing_NotifierUI/Package.swift @@ -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: [] + ) + ] +) diff --git a/Packages/vChewing_NotifierUI/README.md b/Packages/vChewing_NotifierUI/README.md new file mode 100644 index 00000000..eb361d73 --- /dev/null +++ b/Packages/vChewing_NotifierUI/README.md @@ -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. +``` diff --git a/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift new file mode 100644 index 00000000..7fe0fc21 --- /dev/null +++ b/Packages/vChewing_NotifierUI/Sources/NotifierUI/NotifierUI.swift @@ -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 }) + } + } +} diff --git a/Source/Modules/LMMgr.swift b/Source/Modules/LMMgr.swift index 4a3209eb..04897042 100644 --- a/Source/Modules/LMMgr.swift +++ b/Source/Modules/LMMgr.swift @@ -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: "") ) } diff --git a/Source/Modules/UIModules/NotifierUI/NotifierController.swift b/Source/Modules/UIModules/NotifierUI/NotifierController.swift deleted file mode 100644 index f0a7bfcf..00000000 --- a/Source/Modules/UIModules/NotifierUI/NotifierController.swift +++ /dev/null @@ -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() - } -} diff --git a/Source/Modules/ctlInputMethod_Core.swift b/Source/Modules/ctlInputMethod_Core.swift index f6865e35..a4524cf1 100644 --- a/Source/Modules/ctlInputMethod_Core.swift +++ b/Source/Modules/ctlInputMethod_Core.swift @@ -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: "") diff --git a/Source/Modules/ctlInputMethod_Menu.swift b/Source/Modules/ctlInputMethod_Menu.swift index 651fe196..63250b57 100644 --- a/Source/Modules/ctlInputMethod_Menu.swift +++ b/Source/Modules/ctlInputMethod_Menu.swift @@ -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: "") diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index d3b4fb13..481ef283 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -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 = ""; }; 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlAboutWindow.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = ctlCandidate.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - 5B62A34527AE7CD900A19448 /* NotifierController.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = NotifierController.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5B630A3B28CC97020010D076 /* ctlPopupCompositionBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlPopupCompositionBuffer.swift; sourceTree = ""; }; 5B65B919284D0185007C558B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_HandleEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_HandleEvent.swift; sourceTree = ""; }; @@ -246,6 +245,7 @@ 5BC2652127E04B7B00700291 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; lineEnding = 0; path = uninstall.sh; sourceTree = ""; }; 5BC447A228656A1900EDC323 /* Placeholder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Placeholder.swift; sourceTree = ""; }; 5BC447AB2865BEF500EDC323 /* AUTHORS */ = {isa = PBXFileReference; lastKnownFileType = text; path = AUTHORS; sourceTree = ""; }; + 5BC5E01C28DDE4270094E427 /* vChewing_NotifierUI */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = vChewing_NotifierUI; path = Packages/vChewing_NotifierUI; sourceTree = ""; }; 5BCCAFF728DB19A300AB1B27 /* PrefMgr_Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefMgr_Extension.swift; sourceTree = ""; }; 5BD0113C2818543900609769 /* KeyHandler_Core.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; lineEnding = 0; path = KeyHandler_Core.swift; sourceTree = ""; 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 = ""; }; - 5B62A34427AE7CD900A19448 /* NotifierUI */ = { - isa = PBXGroup; - children = ( - 5B62A34527AE7CD900A19448 /* NotifierController.swift */, - ); - path = NotifierUI; - sourceTree = ""; - }; 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;