From 3cb0872a1d0b9dbd407d0fce2bfc5ba0cd525fd5 Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Wed, 7 Sep 2022 19:40:21 +0800 Subject: [PATCH] Repo // Deprecating Zonble's Tooltip controller. --- README-CHT.md | 2 +- README.md | 2 +- .../ControllerModules/IMEStateData.swift | 20 +- .../ctlInputMethod_Core.swift | 4 +- .../ctlInputMethod_HandleDisplay.swift | 14 +- .../ctlInputMethod_HandleStates.swift | 14 +- .../TooltipUI/TooltipController.swift | 172 ----------------- .../UIModules/TooltipUI/ctlTooltip.swift | 176 ++++++++++++++++++ vChewing.xcodeproj/project.pbxproj | 8 +- 9 files changed, 211 insertions(+), 201 deletions(-) delete mode 100644 Source/Modules/UIModules/TooltipUI/TooltipController.swift create mode 100644 Source/Modules/UIModules/TooltipUI/ctlTooltip.swift diff --git a/README-CHT.md b/README-CHT.md index 0f25747b..519af832 100644 --- a/README-CHT.md +++ b/README-CHT.md @@ -88,7 +88,7 @@ - ctlInputMethod 輸入法主控制器內則採用策略設計模式來處理各種狀態。 - 半衰記憶模組的 C++ 原版作者是 Mengjuei Hsieh,且由 Shiki Suen 用 Swift 與 C# 分別重寫、繼續開發。 - 僅供研發人員調試方便而使用的 App 版安裝程式 (by Zonble Yang),不對公眾使用。 -- Voltaire MK2 選字窗、飄雲通知視窗、工具提示 (by Zonble Yang),有大幅度修改。 +- Voltaire MK2 選字窗、飄雲通知視窗 (by Zonble Yang),有大幅度修改。 威注音輸入法 macOS 版以 MIT-NTL License 授權釋出 (與 MIT 相容):© 2021-2022 vChewing 專案。 diff --git a/README.md b/README.md index eaa7503a..fe6a9f04 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ - ctlInputMethod 输入法主控制器内则采用策略设计模式来处理各种状态。 - 半衰记忆模组的 C++ 原版作者是 Mengjuei Hsieh,且由 Shiki Suen 用 Swift 与 C# 分别重写、继续开发。 - 仅供研发人员调试方便而使用的 App 版安装程式 (by Zonble Yang),不对公众使用。 -- Voltaire MK2 选字窗、飘云通知视窗、工具提示 (by Zonble Yang),有大幅度修改。 +- Voltaire MK2 选字窗、飘云通知视窗 (by Zonble Yang),有大幅度修改。 威注音输入法 macOS 版以 MIT-NTL License 授权释出 (与 MIT 相容):© 2021-2022 vChewing 专案。 diff --git a/Source/Modules/ControllerModules/IMEStateData.swift b/Source/Modules/ControllerModules/IMEStateData.swift index 0c930a87..db879003 100644 --- a/Source/Modules/ControllerModules/IMEStateData.swift +++ b/Source/Modules/ControllerModules/IMEStateData.swift @@ -179,7 +179,7 @@ extension StateData { } arrOutput.append(neta) } - return arrOutput.joined(separator: " ") + return arrOutput.joined(separator: "\u{A0}") } /// 更新工具提示內容、以及對應配對是否在庫。 @@ -187,7 +187,7 @@ extension StateData { public static func updateParameters(_ data: inout StateData) { var tooltipGenerated: String { if mgrPrefs.phraseReplacementEnabled { - ctlInputMethod.tooltipController.setColor(state: .warning) + ctlInputMethod.tooltipInstance.setColor(state: .warning) return NSLocalizedString( "⚠︎ Phrase replacement mode enabled, interfering user phrase entry.", comment: "" ) @@ -198,18 +198,18 @@ extension StateData { let text = data.displayedText.charComponents[data.markedRange].joined() if data.markedRange.count < mgrPrefs.allowedMarkRange.lowerBound { - ctlInputMethod.tooltipController.setColor(state: .denialInsufficiency) + ctlInputMethod.tooltipInstance.setColor(state: .denialInsufficiency) return String( format: NSLocalizedString( "\"%@\" length must ≥ 2 for a user phrase.", comment: "" - ) + "\n// " + generateReadingThread(data), text + ) + "\n◆ " + generateReadingThread(data), text ) } else if data.markedRange.count > mgrPrefs.allowedMarkRange.upperBound { - ctlInputMethod.tooltipController.setColor(state: .denialOverflow) + ctlInputMethod.tooltipInstance.setColor(state: .denialOverflow) return String( format: NSLocalizedString( "\"%@\" length should ≤ %d for a user phrase.", comment: "" - ) + "\n// " + generateReadingThread(data), text, mgrPrefs.allowedMarkRange.upperBound + ) + "\n◆ " + generateReadingThread(data), text, mgrPrefs.allowedMarkRange.upperBound ) } @@ -219,17 +219,17 @@ extension StateData { ) if exist { data.markedTargetExists = exist - ctlInputMethod.tooltipController.setColor(state: .prompt) + ctlInputMethod.tooltipInstance.setColor(state: .prompt) return String( format: NSLocalizedString( "\"%@\" already exists:\n ENTER to boost, SHIFT+COMMAND+ENTER to nerf, \n BackSpace or Delete key to exclude.", comment: "" - ) + "\n// " + generateReadingThread(data), text + ) + "\n◆ " + generateReadingThread(data), text ) } - ctlInputMethod.tooltipController.resetColor() + ctlInputMethod.tooltipInstance.resetColor() return String( - format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: "") + "\n// " + format: NSLocalizedString("\"%@\" selected. ENTER to add user phrase.", comment: "") + "\n◆ " + generateReadingThread(data), text ) diff --git a/Source/Modules/ControllerModules/ctlInputMethod_Core.swift b/Source/Modules/ControllerModules/ctlInputMethod_Core.swift index 5d47caeb..56f1617b 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_Core.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_Core.swift @@ -27,8 +27,8 @@ class ctlInputMethod: IMKInputController { static var ctlCandidateCurrent: ctlCandidateProtocol = mgrPrefs.useIMKCandidateWindow ? ctlCandidateIMK.init(.horizontal) : ctlCandidateUniversal.init(.horizontal) - /// 工具提示視窗的副本。 - static let tooltipController = TooltipController() + /// 工具提示視窗的副本,每次都重新初始化。 + static var tooltipInstance = ctlTooltip() // MARK: - diff --git a/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift b/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift index 8e6e9520..d4f71d4f 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_HandleDisplay.swift @@ -27,15 +27,21 @@ extension ctlInputMethod { cursor -= 1 } var finalOrigin: NSPoint = lineHeightRect.origin + let delta: CGFloat = lineHeightRect.size.height + 4.0 // bottomOutOfScreenAdjustmentHeight if isVerticalTyping { finalOrigin = NSPoint( - x: lineHeightRect.origin.x + lineHeightRect.size.width + 4.0, y: lineHeightRect.origin.y - 4.0 + x: lineHeightRect.origin.x + lineHeightRect.size.width + 5, y: lineHeightRect.origin.y + ) + ctlInputMethod.tooltipInstance.show( + tooltip: tooltip, at: finalOrigin, + bottomOutOfScreenAdjustmentHeight: delta, direction: .vertical ) - ctlInputMethod.tooltipController.direction = .vertical } else { - ctlInputMethod.tooltipController.direction = .horizontal + ctlInputMethod.tooltipInstance.show( + tooltip: tooltip, at: finalOrigin, + bottomOutOfScreenAdjustmentHeight: delta, direction: .horizontal + ) } - ctlInputMethod.tooltipController.show(tooltip: tooltip, at: finalOrigin) } func show(candidateWindowWith state: IMEStateProtocol) { diff --git a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift index be42a443..6bb1b30b 100644 --- a/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift +++ b/Source/Modules/ControllerModules/ctlInputMethod_HandleStates.swift @@ -25,7 +25,7 @@ extension ctlInputMethod { case .ofDeactivated: ctlInputMethod.ctlCandidateCurrent.delegate = nil ctlInputMethod.ctlCandidateCurrent.visible = false - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() if previous.hasComposition { commit(text: previous.displayedText) } @@ -39,20 +39,20 @@ extension ctlInputMethod { previous = state } ctlInputMethod.ctlCandidateCurrent.visible = false - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() // 全專案用以判斷「.Abortion」的地方僅此一處。 if previous.hasComposition, state.type != .ofAbortion { commit(text: previous.displayedText) } // 在這裡手動再取消一次選字窗與工具提示的顯示,可謂雙重保險。 ctlInputMethod.ctlCandidateCurrent.visible = false - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() clearInlineDisplay() // 最後一道保險 keyHandler.clear() case .ofCommitting: ctlInputMethod.ctlCandidateCurrent.visible = false - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() let textToCommit = state.textToCommit if !textToCommit.isEmpty { commit(text: textToCommit) } clearInlineDisplay() @@ -60,7 +60,7 @@ extension ctlInputMethod { keyHandler.clear() case .ofInputting: ctlInputMethod.ctlCandidateCurrent.visible = false - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() let textToCommit = state.textToCommit if !textToCommit.isEmpty { commit(text: textToCommit) } setInlineDisplayWithCursor() @@ -74,7 +74,7 @@ extension ctlInputMethod { ctlInputMethod.ctlCandidateCurrent.visible = false setInlineDisplayWithCursor() if state.tooltip.isEmpty { - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() } else { let cursorReference: Int = { if state.data.marker >= state.data.cursor { return state.data.u16Cursor } @@ -86,7 +86,7 @@ extension ctlInputMethod { ) } case .ofCandidates, .ofAssociates, .ofSymbolTable: - ctlInputMethod.tooltipController.hide() + ctlInputMethod.tooltipInstance.hide() setInlineDisplayWithCursor() show(candidateWindowWith: state) default: break diff --git a/Source/Modules/UIModules/TooltipUI/TooltipController.swift b/Source/Modules/UIModules/TooltipUI/TooltipController.swift deleted file mode 100644 index 111576bd..00000000 --- a/Source/Modules/UIModules/TooltipUI/TooltipController.swift +++ /dev/null @@ -1,172 +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. - -import Cocoa - -public class TooltipController: NSWindowController { - public enum ColorStates { - case normal - case redAlert - case warning - case denialOverflow - case denialInsufficiency - case prompt - } - - public enum displayDirection { - case horizontal - case vertical - } - - private var backgroundColor = NSColor.windowBackgroundColor - private var textColor = NSColor.windowBackgroundColor - private var messageTextField: NSTextField - private var tooltip: String = "" { - didSet { - messageTextField.stringValue = tooltip - adjustSize() - } - } - - public var direction: displayDirection = .horizontal - - public init() { - 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.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1) - panel.hasShadow = true - - messageTextField = NSTextField() - messageTextField.isEditable = false - messageTextField.isSelectable = false - messageTextField.isBezeled = false - messageTextField.textColor = textColor - messageTextField.drawsBackground = true - messageTextField.backgroundColor = backgroundColor - messageTextField.font = .systemFont(ofSize: NSFont.systemFontSize(for: .small)) - 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(tooltip: String, at point: NSPoint) { - messageTextField.textColor = textColor - messageTextField.backgroundColor = backgroundColor - self.tooltip = tooltip - window?.orderFront(nil) - set(windowLocation: point) - } - - public func setColor(state: ColorStates) { - switch state { - case .normal: - backgroundColor = NSColor( - red: 0.18, green: 0.18, blue: 0.18, alpha: 1.00 - ) - textColor = NSColor.white - case .redAlert: - backgroundColor = NSColor( - red: 0.55, green: 0.00, blue: 0.00, alpha: 1.00 - ) - textColor = NSColor.white - case .warning: - backgroundColor = NSColor.purple - textColor = NSColor.white - case .denialOverflow: - backgroundColor = NSColor( - red: 0.13, green: 0.08, blue: 0.00, alpha: 1.00 - ) - textColor = NSColor( - red: 1.00, green: 0.60, blue: 0.00, alpha: 1.00 - ) - case .denialInsufficiency: - backgroundColor = NSColor( - red: 0.18, green: 0.18, blue: 0.18, alpha: 1.00 - ) - textColor = NSColor( - red: 0.86, green: 0.86, blue: 0.86, alpha: 1.00 - ) - case .prompt: - backgroundColor = NSColor( - red: 0.00, green: 0.18, blue: 0.13, alpha: 1.00 - ) - textColor = NSColor( - red: 0.00, green: 1.00, blue: 0.74, alpha: 1.00 - ) - } - } - - public func resetColor() { - setColor(state: .normal) - } - - @objc - public func hide() { - window?.orderOut(nil) - } - - private func set(windowLocation windowTopLeftPoint: NSPoint) { - var adjustedPoint = windowTopLeftPoint - adjustedPoint.y -= 5 - - var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.zero - for screen in NSScreen.screens { - let frame = screen.visibleFrame - if windowTopLeftPoint.x >= frame.minX, windowTopLeftPoint.x <= frame.maxX, - windowTopLeftPoint.y >= frame.minY, windowTopLeftPoint.y <= frame.maxY - { - screenFrame = frame - break - } - } - - let windowSize = window?.frame.size ?? NSSize.zero - - // bottom beneath the screen? - if adjustedPoint.y - windowSize.height < screenFrame.minY { - adjustedPoint.y = screenFrame.minY + windowSize.height - } - - // top over the screen? - if adjustedPoint.y >= screenFrame.maxY { - adjustedPoint.y = screenFrame.maxY - 1.0 - } - - // right - if adjustedPoint.x + windowSize.width >= screenFrame.maxX { - adjustedPoint.x = screenFrame.maxX - windowSize.width - } - - // left - if adjustedPoint.x < screenFrame.minX { - adjustedPoint.x = screenFrame.minX - } - - window?.setFrameTopLeftPoint(adjustedPoint) - } - - private func adjustSize() { - let attrString = messageTextField.attributedStringValue - var rect = attrString.boundingRect( - with: NSSize(width: 1600.0, height: 1600.0), options: .usesLineFragmentOrigin - ) - - rect.size.width += 10 - messageTextField.frame = rect - window?.setFrame(rect, display: true) - } -} diff --git a/Source/Modules/UIModules/TooltipUI/ctlTooltip.swift b/Source/Modules/UIModules/TooltipUI/ctlTooltip.swift new file mode 100644 index 00000000..6adbee54 --- /dev/null +++ b/Source/Modules/UIModules/TooltipUI/ctlTooltip.swift @@ -0,0 +1,176 @@ +// (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 ctlTooltip: NSWindowController { + public enum ColorStates { + case normal + case redAlert + case warning + case denialOverflow + case denialInsufficiency + case prompt + } + + private var messageText: NSAttributedTextView + private var tooltip: String = "" { + didSet { + messageText.text = tooltip.isEmpty ? nil : tooltip + adjustSize() + } + } + + public var direction: NSAttributedTextView.writingDirection = .horizontal { + didSet { + messageText.direction = direction + } + } + + public init() { + 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.level = NSWindow.Level(Int(kCGPopUpMenuWindowLevel) + 1) + panel.hasShadow = true + panel.backgroundColor = NSColor.controlBackgroundColor + messageText = NSAttributedTextView() + messageText.backgroundColor = NSColor.controlBackgroundColor + messageText.textColor = NSColor.textColor + panel.contentView?.addSubview(messageText) + super.init(window: panel) + } + + @available(*, unavailable) + public required init?(coder _: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func show( + tooltip: String = "", at point: NSPoint, + bottomOutOfScreenAdjustmentHeight heightDelta: CGFloat, + direction: NSAttributedTextView.writingDirection = .horizontal + ) { + self.direction = direction + messageText.direction = self.direction + self.tooltip = tooltip + window?.orderFront(nil) + set(windowTopLeftPoint: point, bottomOutOfScreenAdjustmentHeight: heightDelta) + } + + public func setColor(state: ColorStates) { + var backgroundColor = NSColor.controlBackgroundColor + var textColor = NSColor.textColor + switch state { + case .normal: + backgroundColor = NSColor( + red: 0.18, green: 0.18, blue: 0.18, alpha: 1.00 + ) + textColor = NSColor.white + case .redAlert: + backgroundColor = NSColor( + red: 0.55, green: 0.00, blue: 0.00, alpha: 1.00 + ) + textColor = NSColor.white + case .warning: + backgroundColor = NSColor.purple + textColor = NSColor.white + case .denialOverflow: + backgroundColor = NSColor( + red: 0.13, green: 0.08, blue: 0.00, alpha: 1.00 + ) + textColor = NSColor( + red: 1.00, green: 0.60, blue: 0.00, alpha: 1.00 + ) + case .denialInsufficiency: + backgroundColor = NSColor.windowBackgroundColor + textColor = NSColor.labelColor + case .prompt: + backgroundColor = NSColor( + red: 0.09, green: 0.15, blue: 0.15, alpha: 1.00 + ) + textColor = NSColor( + red: 0.91, green: 0.95, blue: 0.92, alpha: 1.00 + ) + } + if !IME.isDarkMode { + switch state { + case .denialInsufficiency: break + default: + let colorInterchange = backgroundColor + backgroundColor = textColor + textColor = colorInterchange + } + } + window?.backgroundColor = backgroundColor + messageText.backgroundColor = backgroundColor + messageText.textColor = textColor + } + + public func resetColor() { + setColor(state: .normal) + } + + public func hide() { + window?.orderOut(nil) + } + + private func set(windowTopLeftPoint: NSPoint, bottomOutOfScreenAdjustmentHeight heightDelta: CGFloat) { + guard let window = window else { return } + let windowSize = window.frame.size + + var adjustedPoint = windowTopLeftPoint + var delta = heightDelta + var screenFrame = NSScreen.main?.visibleFrame ?? NSRect.zero + for frame in NSScreen.screens.map(\.visibleFrame).filter({ !$0.contains(windowTopLeftPoint) }) { + screenFrame = frame + break + } + + if delta > screenFrame.size.height / 2.0 { delta = 0.0 } + + if adjustedPoint.y < screenFrame.minY + windowSize.height { + adjustedPoint.y = windowTopLeftPoint.y + windowSize.height + delta + } + adjustedPoint.y = min(adjustedPoint.y, screenFrame.maxY - 1.0) + adjustedPoint.x = min(max(adjustedPoint.x, screenFrame.minX), screenFrame.maxX - windowSize.width - 1.0) + + window.setFrameTopLeftPoint(adjustedPoint) + } + + private func adjustSize() { + let attrString = messageText.attributedStringValue + var rect = attrString.boundingRect( + with: NSSize(width: 1600.0, height: 1600.0), + options: [.usesLineFragmentOrigin, .usesFontLeading, .usesDeviceMetrics] + ) + if direction != .horizontal { + rect = .init(x: rect.minX, y: rect.minY, width: rect.height, height: rect.width) + rect.size.height += NSFont.systemFontSize + rect.size.width *= 1.03 + rect.size.width = max(rect.size.width, NSFont.systemFontSize * 1.05) + rect.size.width = ceil(rect.size.width) + } else { + rect = .init(x: rect.minX, y: rect.minY, width: rect.width, height: rect.height) + rect.size.width += NSFont.systemFontSize + rect.size.height *= 1.03 + rect.size.height = max(rect.size.height, NSFont.systemFontSize * 1.05) + rect.size.height = ceil(rect.size.height) + } + 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 + messageText.frame = rect + window?.setFrame(bigRect, display: true) + messageText.draw(messageText.frame) + } +} diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index 56f02573..06a8596b 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -33,11 +33,11 @@ 5B5948CE289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5948CD289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift */; }; 5B5E535227EF261400C6AA1E /* IME.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5E535127EF261400C6AA1E /* IME.swift */; }; 5B5F8AEB28C86AAD007C11F1 /* NSAttributedTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F8AEA28C86AAD007C11F1 /* NSAttributedTextView.swift */; }; + 5B5F8AEE28C8826D007C11F1 /* ctlTooltip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5F8AED28C8826D007C11F1 /* ctlTooltip.swift */; }; 5B62A32927AE77D100A19448 /* FSEventStreamHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */; }; 5B62A33627AE795800A19448 /* mgrPrefs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33527AE795800A19448 /* mgrPrefs.swift */; }; 5B62A33D27AE7CC100A19448 /* ctlAboutWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A33C27AE7CC100A19448 /* ctlAboutWindow.swift */; }; 5B62A34727AE7CD900A19448 /* ctlCandidate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34027AE7CD900A19448 /* ctlCandidate.swift */; }; - 5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34327AE7CD900A19448 /* TooltipController.swift */; }; 5B62A34A27AE7CD900A19448 /* NotifierController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B62A34527AE7CD900A19448 /* NotifierController.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 */; }; @@ -248,11 +248,11 @@ 5B5948CD289CC04500C85824 /* LMInstantiator_DateTimeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LMInstantiator_DateTimeExtension.swift; sourceTree = ""; }; 5B5E535127EF261400C6AA1E /* IME.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = IME.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5B5F8AEA28C86AAD007C11F1 /* NSAttributedTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSAttributedTextView.swift; sourceTree = ""; }; + 5B5F8AED28C8826D007C11F1 /* ctlTooltip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlTooltip.swift; sourceTree = ""; }; 5B62A32827AE77D100A19448 /* FSEventStreamHelper.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = FSEventStreamHelper.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 5B62A33527AE795800A19448 /* mgrPrefs.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = mgrPrefs.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; 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; }; - 5B62A34327AE7CD900A19448 /* TooltipController.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = TooltipController.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; }; 5B65B919284D0185007C558B /* README-CHT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHT.md"; sourceTree = ""; }; 5B6C141128A9D4B30098ADF8 /* ctlInputMethod_Common.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ctlInputMethod_Common.swift; sourceTree = ""; }; @@ -621,7 +621,7 @@ 5B62A34227AE7CD900A19448 /* TooltipUI */ = { isa = PBXGroup; children = ( - 5B62A34327AE7CD900A19448 /* TooltipController.swift */, + 5B5F8AED28C8826D007C11F1 /* ctlTooltip.swift */, ); path = TooltipUI; sourceTree = ""; @@ -1214,6 +1214,7 @@ D47B92C027972AD100458394 /* main.swift in Sources */, D4A13D5A27A59F0B003BE359 /* ctlInputMethod_Core.swift in Sources */, 5BA9FD4827FEF3C9002DE248 /* PreferencesWindowController.swift in Sources */, + 5B5F8AEE28C8826D007C11F1 /* ctlTooltip.swift in Sources */, 5BD0113B28180D6100609769 /* LMInstantiator.swift in Sources */, 5B2170E7289FACAD00BE7304 /* 1_Compositor.swift in Sources */, 5B21177028753B9D000443A9 /* ctlInputMethod_Delegates.swift in Sources */, @@ -1263,7 +1264,6 @@ 5B40730D281672610023DFFF /* lmReplacements.swift in Sources */, 5B5E535227EF261400C6AA1E /* IME.swift in Sources */, 5B2170E0289FACAD00BE7304 /* 7_LangModel.swift in Sources */, - 5B62A34927AE7CD900A19448 /* TooltipController.swift in Sources */, 5BA9FD4027FEF3C8002DE248 /* Localization.swift in Sources */, 5BF0B84C28C070B000795FC6 /* NSEventExtension.swift in Sources */, 5BAA8FBE282CAF380066C406 /* SyllableComposer.swift in Sources */,