From 962e61f6f314a4f0b9e982edd571374340f590ae Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 8 Feb 2024 01:33:03 +0800 Subject: [PATCH] ClientListMgr // Reimplement without XIB. --- .../ClientListMgr/CtlClientListMgr.swift | 62 ++++ .../ClientListMgr/VwrClientListMgr.swift | 300 +++++++++++------- Source/WindowNIBs/frmClientListMgr.xib | 154 --------- vChewing.xcodeproj/project.pbxproj | 8 - 4 files changed, 252 insertions(+), 272 deletions(-) create mode 100644 Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/CtlClientListMgr.swift rename Source/Modules/WindowControllers/CtlClientListMgr.swift => Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/VwrClientListMgr.swift (62%) delete mode 100644 Source/WindowNIBs/frmClientListMgr.xib diff --git a/Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/CtlClientListMgr.swift b/Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/CtlClientListMgr.swift new file mode 100644 index 00000000..d0f8753d --- /dev/null +++ b/Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/CtlClientListMgr.swift @@ -0,0 +1,62 @@ +// (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 AppKit +import Foundation + +public class CtlClientListMgr: NSWindowController { + let viewController = VwrClientListMgr() + + public static var shared: CtlClientListMgr? + public init() { + super.init( + window: .init( + contentRect: CGRect(x: 401, y: 295, width: 770, height: 335), + styleMask: [.titled, .closable, .miniaturizable], + backing: .buffered, + defer: true + ) + ) + viewController.loadView() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + public static func show() { + if shared == nil { + shared = CtlClientListMgr() + } + guard let shared = shared, let sharedWindow = shared.window else { return } + if !sharedWindow.isVisible { + shared.windowDidLoad() + } + sharedWindow.setPosition(vertical: .center, horizontal: .right, padding: 20) + sharedWindow.orderFrontRegardless() // 逼著視窗往最前方顯示 + sharedWindow.title = "Client Manager".localized + sharedWindow.level = .statusBar + if #available(macOS 10.10, *) { + sharedWindow.titlebarAppearsTransparent = true + } + shared.showWindow(shared) + NSApp.popup() + } + + override public func windowDidLoad() { + super.windowDidLoad() + let view = viewController.view + window?.contentView = view + if let window = window { + var frame = window.frame + frame.size = view.fittingSize + window.setFrame(frame, display: true) + } + window?.setPosition(vertical: .center, horizontal: .right, padding: 20) + } +} diff --git a/Source/Modules/WindowControllers/CtlClientListMgr.swift b/Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/VwrClientListMgr.swift similarity index 62% rename from Source/Modules/WindowControllers/CtlClientListMgr.swift rename to Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/VwrClientListMgr.swift index 9220f489..731eb9d7 100644 --- a/Source/Modules/WindowControllers/CtlClientListMgr.swift +++ b/Packages/vChewing_MainAssembly/Sources/MainAssembly/ClientListMgr/VwrClientListMgr.swift @@ -7,47 +7,119 @@ // requirements defined in MIT License. import AppKit -import MainAssembly +import Foundation +import Shared import UniformTypeIdentifiers -class CtlClientListMgr: NSWindowController, NSTableViewDelegate, NSTableViewDataSource { - @IBOutlet var tblClients: NSTableView! - @IBOutlet var btnRemoveClient: NSButton! - @IBOutlet var btnAddClient: NSButton! - @IBOutlet var lblClientMgrWindow: NSTextField! +public class VwrClientListMgr: NSViewController { + let windowWidth: CGFloat = 770 + let contentWidth: CGFloat = 750 + let buttonWidth: CGFloat = 150 - public static var shared: CtlClientListMgr? + lazy var tblClients: NSTableView = .init() + lazy var btnAddClient = NSButton("Add Client", target: self, action: #selector(btnAddClientClicked(_:))) + lazy var btnRemoveClient = NSButton("Remove Selected", target: self, action: #selector(btnRemoveClientClicked(_:))) + lazy var tableColumn1Cell = NSButtonCell() + lazy var tableColumn1 = NSTableColumn() + lazy var tableColumn2Cell = NSTextFieldCell() + lazy var tableColumn2 = NSTableColumn() - static func show() { - if shared == nil { shared = CtlClientListMgr(windowNibName: "frmClientListMgr") } - guard let shared = shared, let sharedWindow = shared.window else { return } - sharedWindow.setPosition(vertical: .center, horizontal: .right, padding: 20) - sharedWindow.orderFrontRegardless() // 逼著視窗往最前方顯示 - sharedWindow.level = .statusBar - sharedWindow.titlebarAppearsTransparent = true - shared.showWindow(shared) - NSApp.popup() + override public func loadView() { + tblClients.reloadData() + view = body ?? .init() + (view as? NSStackView)?.alignment = .centerX + view.makeSimpleConstraint(.width, relation: .equal, value: windowWidth) + btnRemoveClient.keyEquivalent = .init(NSEvent.SpecialKey.delete.unicodeScalar) } - override func windowDidLoad() { - super.windowDidLoad() - window?.setPosition(vertical: .center, horizontal: .right, padding: 20) - localize() + var body: NSView? { + NSStackView.build(.vertical, insets: .new(all: 14)) { + makeScrollableTable() + .makeSimpleConstraint(.height, relation: .equal, value: 232) + NSStackView.build(.horizontal) { + let descriptionWidth = contentWidth - buttonWidth - 20 + NSStackView.build(.vertical) { + let strDescription = "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable." + strDescription.makeNSLabel(descriptive: true, fixWidth: descriptionWidth) + .makeSimpleConstraint(.width, relation: .greaterThanOrEqual, value: descriptionWidth) + NSView() + } + NSStackView.build(.vertical) { + btnAddClient + .makeSimpleConstraint(.width, relation: .equal, value: buttonWidth) + btnRemoveClient + .makeSimpleConstraint(.width, relation: .equal, value: buttonWidth) + } + } + } + } + + func makeScrollableTable() -> NSScrollView { + let scrollContainer = NSScrollView() + scrollContainer.scrollerStyle = .legacy + scrollContainer.autohidesScrollers = true + scrollContainer.documentView = tblClients + if #available(macOS 11.0, *) { + tblClients.style = .inset + } + tblClients.addTableColumn(tableColumn1) + tblClients.addTableColumn(tableColumn2) + tblClients.headerView = nil tblClients.delegate = self - tblClients.registerForDraggedTypes([.fileURL]) + tblClients.allowsExpansionToolTips = true tblClients.allowsMultipleSelection = true + tblClients.autoresizingMask = [.width, .height] + tblClients.autosaveTableColumns = false + tblClients.backgroundColor = NSColor.controlBackgroundColor + tblClients.columnAutoresizingStyle = .lastColumnOnlyAutoresizingStyle + tblClients.frame = CGRect(x: 0, y: 0, width: 728, height: 230) + tblClients.gridColor = NSColor.clear + tblClients.intercellSpacing = CGSize(width: 17, height: 0) + tblClients.rowHeight = 24 + tblClients.setContentHuggingPriority(.defaultHigh, for: .vertical) + tblClients.registerForDraggedTypes([.init(rawValue: kUTTypeFileURL as String)]) tblClients.dataSource = self tblClients.action = #selector(onItemClicked(_:)) tblClients.target = self - tblClients.reloadData() + if #available(macOS 11.0, *) { tblClients.style = .inset } + + tableColumn1.identifier = NSUserInterfaceItemIdentifier("colPCBEnabled") + tableColumn1.maxWidth = 20 + tableColumn1.minWidth = 20 + tableColumn1.resizingMask = [.autoresizingMask, .userResizingMask] + tableColumn1.width = 20 + tableColumn1.dataCell = tableColumn1Cell + + if #available(macOS 11.0, *) { tableColumn1Cell.controlSize = .large } + tableColumn1Cell.font = NSFont.systemFont(ofSize: 13) + tableColumn1Cell.setButtonType(.switch) + tableColumn1Cell.bezelStyle = .rounded + + tableColumn2.identifier = NSUserInterfaceItemIdentifier("colClient") + tableColumn2.maxWidth = 1000 + tableColumn2.minWidth = 40 + tableColumn2.resizingMask = [.autoresizingMask, .userResizingMask] + tableColumn2.width = 546 + tableColumn2.dataCell = tableColumn2Cell + + tableColumn2Cell.backgroundColor = NSColor.controlBackgroundColor + tableColumn2Cell.font = NSFont.systemFont(ofSize: 20) + tableColumn2Cell.isEditable = true + tableColumn2Cell.isSelectable = true + tableColumn2Cell.lineBreakMode = .byTruncatingTail + tableColumn2Cell.stringValue = "Text Cell" + tableColumn2Cell.textColor = NSColor.controlTextColor + tableColumn2Cell.isEditable = true + + return scrollContainer } } -// MARK: - UserDefaults Handlers +// MARK: - UserDefaults Handlers. -extension CtlClientListMgr { - public static var clientsList: [String] { PrefMgr.shared.clientsIMKTextInputIncapable.keys.sorted() } - public static func removeClient(at index: Int) { +public extension VwrClientListMgr { + static var clientsList: [String] { PrefMgr.shared.clientsIMKTextInputIncapable.keys.sorted() } + static func removeClient(at index: Int) { guard index < Self.clientsList.count else { return } let key = Self.clientsList[index] var dict = PrefMgr.shared.clientsIMKTextInputIncapable @@ -56,15 +128,75 @@ extension CtlClientListMgr { } } -// MARK: - Implementations +// MARK: - Common Operation Methods. -extension CtlClientListMgr { - func numberOfRows(in _: NSTableView) -> Int { - Self.clientsList.count +extension VwrClientListMgr { + func applyNewValue(_ newValue: String, highMitigation mitigation: Bool = true) { + guard !newValue.isEmpty else { return } + var dict = PrefMgr.shared.clientsIMKTextInputIncapable + dict[newValue] = mitigation + PrefMgr.shared.clientsIMKTextInputIncapable = dict + tblClients.reloadData() + btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains( + tblClients.selectedRow) + } + + /// 檢查傳入的 NSDraggingInfo 當中的 URL 對應的物件是否是 App Bundle。 + /// - Parameters: + /// - info: 傳入的 NSDraggingInfo 物件。 + /// - onError: 當不滿足判定條件時,執行給定的 lambda expression。 + /// - handler: 當滿足判定條件時,讓傳入的 lambda expression 處理已經整理出來的 URL 陣列。 + private func validatePasteboardForAppBundles( + neta info: NSDraggingInfo, onError: @escaping () -> Void?, handler: (([URL]) -> Void)? = nil + ) { + let board = info.draggingPasteboard + let type = NSPasteboard.PasteboardType(rawValue: kUTTypeApplicationBundle as String) + let options: [NSPasteboard.ReadingOptionKey: Any] = [ + .urlReadingFileURLsOnly: true, + .urlReadingContentsConformToTypes: [type], + ] + guard let urls = board.readObjects(forClasses: [NSURL.self], options: options) as? [URL], !urls.isEmpty else { + onError() + return + } + if let handler = handler { + handler(urls) + } + } +} + +// MARK: - IBActions. + +extension VwrClientListMgr { + @IBAction func onItemClicked(_: Any!) { + guard tblClients.clickedColumn == 0 else { return } + PrefMgr.shared.clientsIMKTextInputIncapable[Self.clientsList[tblClients.clickedRow]]?.toggle() + tblClients.reloadData() + } + + @IBAction func btnRemoveClientClicked(_: Any) { + guard let minIndexSelected = tblClients.selectedRowIndexes.min() else { return } + if minIndexSelected >= Self.clientsList.count { return } + if minIndexSelected < 0 { return } + var isLastRow = false + tblClients.selectedRowIndexes.sorted().reversed().forEach { index in + isLastRow = { + if Self.clientsList.count < 2 { return false } + return minIndexSelected == Self.clientsList.count - 1 + }() + if index < Self.clientsList.count { + Self.removeClient(at: index) + } + } + if isLastRow { + tblClients.selectRowIndexes(.init(arrayLiteral: minIndexSelected - 1), byExtendingSelection: false) + } + tblClients.reloadData() + btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(minIndexSelected) } @IBAction func btnAddClientClicked(_: Any) { - guard let window = window else { return } + guard let window = NSApp.keyWindow else { return } let alert = NSAlert() alert.messageText = NSLocalizedString( "Please enter the client app bundle identifier(s) you want to register.", comment: "" @@ -86,6 +218,7 @@ extension CtlClientListMgr { scrollview.verticalScroller?.scrollerStyle = .legacy scrollview.autoresizingMask = [.width, .height] let theTextView = NSTextView(frame: NSRect(x: 0, y: 0, width: contentSize.width, height: contentSize.height)) + scrollview.documentView = theTextView theTextView.minSize = NSSize(width: 0.0, height: contentSize.height) theTextView.maxSize = NSSize(width: maxFloat, height: maxFloat) theTextView.isVerticallyResizable = true @@ -93,7 +226,6 @@ extension CtlClientListMgr { 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] @@ -109,7 +241,7 @@ extension CtlClientListMgr { }() alert.accessoryView = scrollview - alert.beginSheetModal(for: window) { result in + alert.beginSheetModal(at: window) { result in resultCheck: switch result { case .alertFirstButtonReturn, .alertSecondButtonReturn: theTextView.textContainer?.textView?.string.components(separatedBy: "\n").filter { !$0.isEmpty }.forEach { @@ -126,12 +258,16 @@ extension CtlClientListMgr { ) dlgOpenPath.showsResizeIndicator = true dlgOpenPath.allowsMultipleSelection = true - dlgOpenPath.allowedContentTypes = [UTType.applicationBundle] + if #available(macOS 11.0, *) { + dlgOpenPath.allowedContentTypes = [.applicationBundle] + } else { + dlgOpenPath.allowedFileTypes = ["app"] + } dlgOpenPath.allowsOtherFileTypes = false dlgOpenPath.showsHiddenFiles = true dlgOpenPath.canChooseFiles = true dlgOpenPath.canChooseDirectories = false - dlgOpenPath.beginSheetModal(for: window) { result in + dlgOpenPath.beginSheetModal(at: window) { result in switch result { case .OK: for url in dlgOpenPath.urls { @@ -141,11 +277,11 @@ extension CtlClientListMgr { ) let text = url.path + "\n\n" + NSLocalizedString("Please try again.", comment: "") guard let bundle = Bundle(url: url) else { - self.window?.callAlert(title: title, text: text) + NSApp.keyWindow?.callAlert(title: title, text: text) return } guard let identifier = bundle.bundleIdentifier else { - self.window?.callAlert(title: title, text: text) + NSApp.keyWindow?.callAlert(title: title, text: text) return } let isIdentifierAlreadyRegistered = Self.clientsList.contains(identifier) @@ -171,49 +307,20 @@ extension CtlClientListMgr { } } } +} - private func applyNewValue(_ newValue: String, highMitigation mitigation: Bool = true) { - guard !newValue.isEmpty else { return } - var dict = PrefMgr.shared.clientsIMKTextInputIncapable - dict[newValue] = mitigation - PrefMgr.shared.clientsIMKTextInputIncapable = dict - tblClients.reloadData() - btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains( - tblClients.selectedRow) +// MARK: - TableView Extensions. + +extension VwrClientListMgr: NSTableViewDelegate, NSTableViewDataSource { + public func numberOfRows(in _: NSTableView) -> Int { + Self.clientsList.count } - @IBAction func btnRemoveClientClicked(_: Any) { - guard let minIndexSelected = tblClients.selectedRowIndexes.min() else { return } - if minIndexSelected >= Self.clientsList.count { return } - if minIndexSelected < 0 { return } - var isLastRow = false - tblClients.selectedRowIndexes.sorted().reversed().forEach { index in - isLastRow = { - if Self.clientsList.count < 2 { return false } - return minIndexSelected == Self.clientsList.count - 1 - }() - if index < Self.clientsList.count { - Self.removeClient(at: index) - } - } - if isLastRow { - tblClients.selectRowIndexes(.init(arrayLiteral: minIndexSelected - 1), byExtendingSelection: false) - } - tblClients.reloadData() - btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(minIndexSelected) - } - - @objc func onItemClicked(_: Any!) { - guard tblClients.clickedColumn == 0 else { return } - PrefMgr.shared.clientsIMKTextInputIncapable[Self.clientsList[tblClients.clickedRow]]?.toggle() - tblClients.reloadData() - } - - func tableView(_: NSTableView, shouldEdit _: NSTableColumn?, row _: Int) -> Bool { + public func tableView(_: NSTableView, shouldEdit _: NSTableColumn?, row _: Int) -> Bool { false } - func tableView(_: NSTableView, objectValueFor column: NSTableColumn?, row: Int) -> Any? { + public func tableView(_: NSTableView, objectValueFor column: NSTableColumn?, row: Int) -> Any? { defer { self.btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains( self.tblClients.selectedRow) @@ -232,30 +339,7 @@ extension CtlClientListMgr { return Self.clientsList[row] } - /// 檢查傳入的 NSDraggingInfo 當中的 URL 對應的物件是否是 App Bundle。 - /// - Parameters: - /// - info: 傳入的 NSDraggingInfo 物件。 - /// - onError: 當不滿足判定條件時,執行給定的 lambda expression。 - /// - handler: 當滿足判定條件時,讓傳入的 lambda expression 處理已經整理出來的 URL 陣列。 - private func validatePasteboardForAppBundles( - neta info: NSDraggingInfo, onError: @escaping () -> Void?, handler: (([URL]) -> Void)? = nil - ) { - let board = info.draggingPasteboard - let type = UTType.applicationBundle - let options: [NSPasteboard.ReadingOptionKey: Any] = [ - .urlReadingFileURLsOnly: true, - .urlReadingContentsConformToTypes: [type], - ] - guard let urls = board.readObjects(forClasses: [NSURL.self], options: options) as? [URL], !urls.isEmpty else { - onError() - return - } - if let handler = handler { - handler(urls) - } - } - - func tableView( + public func tableView( _: NSTableView, validateDrop info: NSDraggingInfo, proposedRow _: Int, proposedDropOperation _: NSTableView.DropOperation ) -> NSDragOperation { @@ -266,7 +350,7 @@ extension CtlClientListMgr { return result } - func tableView( + public func tableView( _: NSTableView, acceptDrop info: NSDraggingInfo, row _: Int, dropOperation _: NSTableView.DropOperation ) -> Bool { @@ -285,15 +369,11 @@ extension CtlClientListMgr { defer { if result { tblClients.reloadData() } } return result } - - private func localize() { - guard let window = window else { return } - window.title = NSLocalizedString("Client Manager", comment: "") - lblClientMgrWindow.stringValue = NSLocalizedString( - "Please manage the list of those clients here which are: 1) IMKTextInput-incompatible; 2) suspected from abusing the contents of the inline composition buffer. A client listed here, if checked, will use popup composition buffer with maximum 20 reading counts holdable.", - comment: "" - ) - btnAddClient.title = NSLocalizedString("Add Client", comment: "") - btnRemoveClient.title = NSLocalizedString("Remove Selected", comment: "") - } +} + +// MARK: - Preview. + +@available(macOS 14.0, *) +#Preview(traits: .fixedLayout(width: 770, height: 335)) { + VwrClientListMgr() } diff --git a/Source/WindowNIBs/frmClientListMgr.xib b/Source/WindowNIBs/frmClientListMgr.xib deleted file mode 100644 index 17b8c78b..00000000 --- a/Source/WindowNIBs/frmClientListMgr.xib +++ /dev/null @@ -1,154 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/vChewing.xcodeproj/project.pbxproj b/vChewing.xcodeproj/project.pbxproj index eeb0a0a1..df73e95a 100644 --- a/vChewing.xcodeproj/project.pbxproj +++ b/vChewing.xcodeproj/project.pbxproj @@ -8,8 +8,6 @@ /* Begin PBXBuildFile section */ 5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; }; - 5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */; }; - 5B0EF55F28CDBF8E00F8F7CE /* CtlClientListMgr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */; }; 5B2CA1E62B130869002634EE /* vChewingFactoryDatabase.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 5B2CA1E52B130869002634EE /* vChewingFactoryDatabase.sqlite */; }; 5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */; }; 5B40113928D7050D00A9D4CB /* Shared in Frameworks */ = {isa = PBXBuildFile; productRef = 5B40113828D7050D00A9D4CB /* Shared */; }; @@ -111,8 +109,6 @@ 5B09307A28B6FC400021F8C5 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = en; path = en.lproj/shortcuts.html; sourceTree = ""; }; 5B09307B28B6FC410021F8C5 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = ja; path = ja.lproj/shortcuts.html; sourceTree = ""; }; 5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = ""; tabWidth = 2; usesTabs = 0; }; - 5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = frmClientListMgr.xib; sourceTree = ""; }; - 5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CtlClientListMgr.swift; sourceTree = ""; }; 5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = ""; }; 5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; 5B18BA7127C7BD8B0056EB19 /* README-CHS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHS.md"; sourceTree = ""; }; @@ -293,7 +289,6 @@ 5B62A33A27AE7C7500A19448 /* WindowControllers */ = { isa = PBXGroup; children = ( - 5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */, 5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */, ); path = WindowControllers; @@ -302,7 +297,6 @@ 5B62A33B27AE7C7F00A19448 /* WindowNIBs */ = { isa = PBXGroup; children = ( - 5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */, 6A187E2816004C5900466B2E /* MainMenu.xib */, ); path = WindowNIBs; @@ -597,7 +591,6 @@ 5B70F4EC2A0BE900005EA8C4 /* MenuIcon-TCVIM@2x.png in Resources */, 5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */, 5B7DA80328BF6BC600D7B2AD /* fixinstall.sh in Resources */, - 5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */, 5B70F4E92A0BE900005EA8C4 /* MenuIcon-TCVIM.png in Resources */, 5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */, 6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */, @@ -727,7 +720,6 @@ files = ( D427F76C278CA2B0004A2160 /* AppDelegateImpl.swift in Sources */, D47B92C027972AD100458394 /* main.swift in Sources */, - 5B0EF55F28CDBF8E00F8F7CE /* CtlClientListMgr.swift in Sources */, 5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */, 5BB802DA27FABA8300CF1C19 /* SessionCtl_Menu.swift in Sources */, );