ClientListMgr // Reimplement without XIB.
This commit is contained in:
parent
8679943b9d
commit
962e61f6f3
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,47 +7,119 @@
|
||||||
// requirements defined in MIT License.
|
// requirements defined in MIT License.
|
||||||
|
|
||||||
import AppKit
|
import AppKit
|
||||||
import MainAssembly
|
import Foundation
|
||||||
|
import Shared
|
||||||
import UniformTypeIdentifiers
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
class CtlClientListMgr: NSWindowController, NSTableViewDelegate, NSTableViewDataSource {
|
public class VwrClientListMgr: NSViewController {
|
||||||
@IBOutlet var tblClients: NSTableView!
|
let windowWidth: CGFloat = 770
|
||||||
@IBOutlet var btnRemoveClient: NSButton!
|
let contentWidth: CGFloat = 750
|
||||||
@IBOutlet var btnAddClient: NSButton!
|
let buttonWidth: CGFloat = 150
|
||||||
@IBOutlet var lblClientMgrWindow: NSTextField!
|
|
||||||
|
|
||||||
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() {
|
override public func loadView() {
|
||||||
if shared == nil { shared = CtlClientListMgr(windowNibName: "frmClientListMgr") }
|
tblClients.reloadData()
|
||||||
guard let shared = shared, let sharedWindow = shared.window else { return }
|
view = body ?? .init()
|
||||||
sharedWindow.setPosition(vertical: .center, horizontal: .right, padding: 20)
|
(view as? NSStackView)?.alignment = .centerX
|
||||||
sharedWindow.orderFrontRegardless() // 逼著視窗往最前方顯示
|
view.makeSimpleConstraint(.width, relation: .equal, value: windowWidth)
|
||||||
sharedWindow.level = .statusBar
|
btnRemoveClient.keyEquivalent = .init(NSEvent.SpecialKey.delete.unicodeScalar)
|
||||||
sharedWindow.titlebarAppearsTransparent = true
|
|
||||||
shared.showWindow(shared)
|
|
||||||
NSApp.popup()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func windowDidLoad() {
|
var body: NSView? {
|
||||||
super.windowDidLoad()
|
NSStackView.build(.vertical, insets: .new(all: 14)) {
|
||||||
window?.setPosition(vertical: .center, horizontal: .right, padding: 20)
|
makeScrollableTable()
|
||||||
localize()
|
.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.delegate = self
|
||||||
tblClients.registerForDraggedTypes([.fileURL])
|
tblClients.allowsExpansionToolTips = true
|
||||||
tblClients.allowsMultipleSelection = 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.dataSource = self
|
||||||
tblClients.action = #selector(onItemClicked(_:))
|
tblClients.action = #selector(onItemClicked(_:))
|
||||||
tblClients.target = self
|
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 extension VwrClientListMgr {
|
||||||
public static var clientsList: [String] { PrefMgr.shared.clientsIMKTextInputIncapable.keys.sorted() }
|
static var clientsList: [String] { PrefMgr.shared.clientsIMKTextInputIncapable.keys.sorted() }
|
||||||
public static func removeClient(at index: Int) {
|
static func removeClient(at index: Int) {
|
||||||
guard index < Self.clientsList.count else { return }
|
guard index < Self.clientsList.count else { return }
|
||||||
let key = Self.clientsList[index]
|
let key = Self.clientsList[index]
|
||||||
var dict = PrefMgr.shared.clientsIMKTextInputIncapable
|
var dict = PrefMgr.shared.clientsIMKTextInputIncapable
|
||||||
|
@ -56,15 +128,75 @@ extension CtlClientListMgr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Implementations
|
// MARK: - Common Operation Methods.
|
||||||
|
|
||||||
extension CtlClientListMgr {
|
extension VwrClientListMgr {
|
||||||
func numberOfRows(in _: NSTableView) -> Int {
|
func applyNewValue(_ newValue: String, highMitigation mitigation: Bool = true) {
|
||||||
Self.clientsList.count
|
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) {
|
@IBAction func btnAddClientClicked(_: Any) {
|
||||||
guard let window = window else { return }
|
guard let window = NSApp.keyWindow else { return }
|
||||||
let alert = NSAlert()
|
let alert = NSAlert()
|
||||||
alert.messageText = NSLocalizedString(
|
alert.messageText = NSLocalizedString(
|
||||||
"Please enter the client app bundle identifier(s) you want to register.", comment: ""
|
"Please enter the client app bundle identifier(s) you want to register.", comment: ""
|
||||||
|
@ -86,6 +218,7 @@ extension CtlClientListMgr {
|
||||||
scrollview.verticalScroller?.scrollerStyle = .legacy
|
scrollview.verticalScroller?.scrollerStyle = .legacy
|
||||||
scrollview.autoresizingMask = [.width, .height]
|
scrollview.autoresizingMask = [.width, .height]
|
||||||
let theTextView = NSTextView(frame: NSRect(x: 0, y: 0, width: contentSize.width, height: contentSize.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.minSize = NSSize(width: 0.0, height: contentSize.height)
|
||||||
theTextView.maxSize = NSSize(width: maxFloat, height: maxFloat)
|
theTextView.maxSize = NSSize(width: maxFloat, height: maxFloat)
|
||||||
theTextView.isVerticallyResizable = true
|
theTextView.isVerticallyResizable = true
|
||||||
|
@ -93,7 +226,6 @@ extension CtlClientListMgr {
|
||||||
theTextView.autoresizingMask = .width
|
theTextView.autoresizingMask = .width
|
||||||
theTextView.textContainer?.containerSize = NSSize(width: contentSize.width, height: maxFloat)
|
theTextView.textContainer?.containerSize = NSSize(width: contentSize.width, height: maxFloat)
|
||||||
theTextView.textContainer?.widthTracksTextView = true
|
theTextView.textContainer?.widthTracksTextView = true
|
||||||
scrollview.documentView = theTextView
|
|
||||||
theTextView.enclosingScrollView?.hasHorizontalScroller = true
|
theTextView.enclosingScrollView?.hasHorizontalScroller = true
|
||||||
theTextView.isHorizontallyResizable = true
|
theTextView.isHorizontallyResizable = true
|
||||||
theTextView.autoresizingMask = [.width, .height]
|
theTextView.autoresizingMask = [.width, .height]
|
||||||
|
@ -109,7 +241,7 @@ extension CtlClientListMgr {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
alert.accessoryView = scrollview
|
alert.accessoryView = scrollview
|
||||||
alert.beginSheetModal(for: window) { result in
|
alert.beginSheetModal(at: window) { result in
|
||||||
resultCheck: switch result {
|
resultCheck: switch result {
|
||||||
case .alertFirstButtonReturn, .alertSecondButtonReturn:
|
case .alertFirstButtonReturn, .alertSecondButtonReturn:
|
||||||
theTextView.textContainer?.textView?.string.components(separatedBy: "\n").filter { !$0.isEmpty }.forEach {
|
theTextView.textContainer?.textView?.string.components(separatedBy: "\n").filter { !$0.isEmpty }.forEach {
|
||||||
|
@ -126,12 +258,16 @@ extension CtlClientListMgr {
|
||||||
)
|
)
|
||||||
dlgOpenPath.showsResizeIndicator = true
|
dlgOpenPath.showsResizeIndicator = true
|
||||||
dlgOpenPath.allowsMultipleSelection = true
|
dlgOpenPath.allowsMultipleSelection = true
|
||||||
dlgOpenPath.allowedContentTypes = [UTType.applicationBundle]
|
if #available(macOS 11.0, *) {
|
||||||
|
dlgOpenPath.allowedContentTypes = [.applicationBundle]
|
||||||
|
} else {
|
||||||
|
dlgOpenPath.allowedFileTypes = ["app"]
|
||||||
|
}
|
||||||
dlgOpenPath.allowsOtherFileTypes = false
|
dlgOpenPath.allowsOtherFileTypes = false
|
||||||
dlgOpenPath.showsHiddenFiles = true
|
dlgOpenPath.showsHiddenFiles = true
|
||||||
dlgOpenPath.canChooseFiles = true
|
dlgOpenPath.canChooseFiles = true
|
||||||
dlgOpenPath.canChooseDirectories = false
|
dlgOpenPath.canChooseDirectories = false
|
||||||
dlgOpenPath.beginSheetModal(for: window) { result in
|
dlgOpenPath.beginSheetModal(at: window) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .OK:
|
case .OK:
|
||||||
for url in dlgOpenPath.urls {
|
for url in dlgOpenPath.urls {
|
||||||
|
@ -141,11 +277,11 @@ extension CtlClientListMgr {
|
||||||
)
|
)
|
||||||
let text = url.path + "\n\n" + NSLocalizedString("Please try again.", comment: "")
|
let text = url.path + "\n\n" + NSLocalizedString("Please try again.", comment: "")
|
||||||
guard let bundle = Bundle(url: url) else {
|
guard let bundle = Bundle(url: url) else {
|
||||||
self.window?.callAlert(title: title, text: text)
|
NSApp.keyWindow?.callAlert(title: title, text: text)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard let identifier = bundle.bundleIdentifier else {
|
guard let identifier = bundle.bundleIdentifier else {
|
||||||
self.window?.callAlert(title: title, text: text)
|
NSApp.keyWindow?.callAlert(title: title, text: text)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let isIdentifierAlreadyRegistered = Self.clientsList.contains(identifier)
|
let isIdentifierAlreadyRegistered = Self.clientsList.contains(identifier)
|
||||||
|
@ -171,49 +307,20 @@ extension CtlClientListMgr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func applyNewValue(_ newValue: String, highMitigation mitigation: Bool = true) {
|
// MARK: - TableView Extensions.
|
||||||
guard !newValue.isEmpty else { return }
|
|
||||||
var dict = PrefMgr.shared.clientsIMKTextInputIncapable
|
extension VwrClientListMgr: NSTableViewDelegate, NSTableViewDataSource {
|
||||||
dict[newValue] = mitigation
|
public func numberOfRows(in _: NSTableView) -> Int {
|
||||||
PrefMgr.shared.clientsIMKTextInputIncapable = dict
|
Self.clientsList.count
|
||||||
tblClients.reloadData()
|
|
||||||
btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(
|
|
||||||
tblClients.selectedRow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func btnRemoveClientClicked(_: Any) {
|
public func tableView(_: NSTableView, shouldEdit _: NSTableColumn?, row _: Int) -> Bool {
|
||||||
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 {
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(_: NSTableView, objectValueFor column: NSTableColumn?, row: Int) -> Any? {
|
public func tableView(_: NSTableView, objectValueFor column: NSTableColumn?, row: Int) -> Any? {
|
||||||
defer {
|
defer {
|
||||||
self.btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(
|
self.btnRemoveClient.isEnabled = (0 ..< Self.clientsList.count).contains(
|
||||||
self.tblClients.selectedRow)
|
self.tblClients.selectedRow)
|
||||||
|
@ -232,30 +339,7 @@ extension CtlClientListMgr {
|
||||||
return Self.clientsList[row]
|
return Self.clientsList[row]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 檢查傳入的 NSDraggingInfo 當中的 URL 對應的物件是否是 App Bundle。
|
public func tableView(
|
||||||
/// - 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(
|
|
||||||
_: NSTableView, validateDrop info: NSDraggingInfo, proposedRow _: Int,
|
_: NSTableView, validateDrop info: NSDraggingInfo, proposedRow _: Int,
|
||||||
proposedDropOperation _: NSTableView.DropOperation
|
proposedDropOperation _: NSTableView.DropOperation
|
||||||
) -> NSDragOperation {
|
) -> NSDragOperation {
|
||||||
|
@ -266,7 +350,7 @@ extension CtlClientListMgr {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableView(
|
public func tableView(
|
||||||
_: NSTableView, acceptDrop info: NSDraggingInfo,
|
_: NSTableView, acceptDrop info: NSDraggingInfo,
|
||||||
row _: Int, dropOperation _: NSTableView.DropOperation
|
row _: Int, dropOperation _: NSTableView.DropOperation
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
|
@ -285,15 +369,11 @@ extension CtlClientListMgr {
|
||||||
defer { if result { tblClients.reloadData() } }
|
defer { if result { tblClients.reloadData() } }
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
private func localize() {
|
|
||||||
guard let window = window else { return }
|
// MARK: - Preview.
|
||||||
window.title = NSLocalizedString("Client Manager", comment: "")
|
|
||||||
lblClientMgrWindow.stringValue = NSLocalizedString(
|
@available(macOS 14.0, *)
|
||||||
"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.",
|
#Preview(traits: .fixedLayout(width: 770, height: 335)) {
|
||||||
comment: ""
|
VwrClientListMgr()
|
||||||
)
|
|
||||||
btnAddClient.title = NSLocalizedString("Add Client", comment: "")
|
|
||||||
btnRemoveClient.title = NSLocalizedString("Remove Selected", comment: "")
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,154 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
|
||||||
<dependencies>
|
|
||||||
<deployment identifier="macosx"/>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
|
|
||||||
<capability name="System colors introduced in macOS 10.14" minToolsVersion="10.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="CtlClientListMgr" customModule="vChewing" customModuleProvider="target">
|
|
||||||
<connections>
|
|
||||||
<outlet property="btnAddClient" destination="JcI-Ff-tDM" id="XbA-OK-zl8"/>
|
|
||||||
<outlet property="btnRemoveClient" destination="UNR-wG-8n1" id="vkb-81-1hA"/>
|
|
||||||
<outlet property="lblClientMgrWindow" destination="3ev-ns-FKY" id="VqL-RC-OdY"/>
|
|
||||||
<outlet property="tblClients" destination="vIw-vc-WKJ" id="2lw-U5-JAh"/>
|
|
||||||
<outlet property="window" destination="F0z-JX-Cv5" id="gIp-Ho-8D9"/>
|
|
||||||
</connections>
|
|
||||||
</customObject>
|
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
|
||||||
<window title="Client Manager" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" titlebarAppearsTransparent="YES" id="F0z-JX-Cv5">
|
|
||||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" fullSizeContentView="YES"/>
|
|
||||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
|
||||||
<rect key="contentRect" x="196" y="240" width="770" height="335"/>
|
|
||||||
<rect key="screenRect" x="0.0" y="0.0" width="1920" height="1055"/>
|
|
||||||
<view key="contentView" id="se5-gp-TjO" customClass="NSVisualEffectView" customModule="vChewing" customModuleProvider="target">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="770" height="335"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<subviews>
|
|
||||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="3ev-ns-FKY" userLabel="lblClientMgrWindow">
|
|
||||||
<rect key="frame" x="18" y="20" width="600" height="46"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="46" id="HDu-vv-Kcv"/>
|
|
||||||
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="490" id="LhL-fH-PVL"/>
|
|
||||||
</constraints>
|
|
||||||
<textFieldCell key="cell" title="Placeholder for description texts." id="hvd-Wx-n7n">
|
|
||||||
<font key="font" metaFont="smallSystem"/>
|
|
||||||
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
</textField>
|
|
||||||
<scrollView autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MUP-Im-g6c">
|
|
||||||
<rect key="frame" x="20" y="76" width="730" height="232"/>
|
|
||||||
<clipView key="contentView" drawsBackground="NO" id="wKQ-IV-k62">
|
|
||||||
<rect key="frame" x="1" y="1" width="728" height="230"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" tableStyle="inset" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" id="vIw-vc-WKJ" userLabel="tblClients">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="728" height="230"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<size key="intercellSpacing" width="17" height="0.0"/>
|
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="gridColor" name="separatorColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<tableColumns>
|
|
||||||
<tableColumn identifier="colPCBEnabled" width="20" minWidth="20" maxWidth="20" id="6D6-O8-Zrc">
|
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
|
||||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</tableHeaderCell>
|
|
||||||
<buttonCell key="dataCell" type="check" bezelStyle="regularSquare" imagePosition="left" controlSize="large" inset="2" id="5Bp-jJ-Sf1">
|
|
||||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
</buttonCell>
|
|
||||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
|
||||||
</tableColumn>
|
|
||||||
<tableColumn identifier="colClient" width="546" minWidth="40" maxWidth="1000" id="kWw-Lj-EFx">
|
|
||||||
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
|
|
||||||
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</tableHeaderCell>
|
|
||||||
<textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="evF-0c-DTr">
|
|
||||||
<font key="font" metaFont="system" size="20"/>
|
|
||||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
|
|
||||||
</textFieldCell>
|
|
||||||
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
|
|
||||||
</tableColumn>
|
|
||||||
</tableColumns>
|
|
||||||
</tableView>
|
|
||||||
</subviews>
|
|
||||||
<nil key="backgroundColor"/>
|
|
||||||
</clipView>
|
|
||||||
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="6Wq-mB-m8K">
|
|
||||||
<rect key="frame" x="1" y="215" width="622" height="16"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
</scroller>
|
|
||||||
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="rYb-HR-4th">
|
|
||||||
<rect key="frame" x="224" y="17" width="15" height="102"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
</scroller>
|
|
||||||
</scrollView>
|
|
||||||
<customView translatesAutoresizingMaskIntoConstraints="NO" id="qCN-8Z-3x3">
|
|
||||||
<rect key="frame" x="624" y="20" width="126" height="46"/>
|
|
||||||
<subviews>
|
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="JcI-Ff-tDM" userLabel="btnAddClient">
|
|
||||||
<rect key="frame" x="-7" y="19" width="140" height="32"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="width" constant="126" id="YS5-dM-Awj"/>
|
|
||||||
</constraints>
|
|
||||||
<buttonCell key="cell" type="push" title="Add" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="7rO-JZ-kgV">
|
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
</buttonCell>
|
|
||||||
<connections>
|
|
||||||
<action selector="btnAddClientClicked:" target="-2" id="klb-NT-gqr"/>
|
|
||||||
</connections>
|
|
||||||
</button>
|
|
||||||
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="UNR-wG-8n1" userLabel="btnRemoveClient">
|
|
||||||
<rect key="frame" x="-7" y="-7" width="140" height="32"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="width" constant="126" id="t4F-yV-r4E"/>
|
|
||||||
</constraints>
|
|
||||||
<buttonCell key="cell" type="push" title="Remove" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="wNc-xy-U4i">
|
|
||||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
|
||||||
<font key="font" metaFont="system"/>
|
|
||||||
<string key="keyEquivalent" base64-UTF8="YES">
|
|
||||||
CA
|
|
||||||
</string>
|
|
||||||
</buttonCell>
|
|
||||||
<connections>
|
|
||||||
<action selector="btnRemoveClientClicked:" target="-2" id="VbY-dw-fRP"/>
|
|
||||||
</connections>
|
|
||||||
</button>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="JcI-Ff-tDM" firstAttribute="trailing" secondItem="UNR-wG-8n1" secondAttribute="trailing" id="3Fe-KL-u9x"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="UNR-wG-8n1" secondAttribute="bottom" id="5MS-Xg-KDM"/>
|
|
||||||
<constraint firstItem="JcI-Ff-tDM" firstAttribute="top" secondItem="qCN-8Z-3x3" secondAttribute="top" id="DZc-Jc-kVr"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="JcI-Ff-tDM" secondAttribute="trailing" id="foA-xu-NF8"/>
|
|
||||||
<constraint firstItem="JcI-Ff-tDM" firstAttribute="leading" secondItem="UNR-wG-8n1" secondAttribute="leading" id="hOp-FU-UKN"/>
|
|
||||||
<constraint firstItem="JcI-Ff-tDM" firstAttribute="leading" secondItem="qCN-8Z-3x3" secondAttribute="leading" id="r1x-vo-9qt"/>
|
|
||||||
</constraints>
|
|
||||||
</customView>
|
|
||||||
</subviews>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="3ev-ns-FKY" firstAttribute="top" secondItem="MUP-Im-g6c" secondAttribute="bottom" constant="10" id="2tx-uw-Zdh"/>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="3ev-ns-FKY" secondAttribute="bottom" constant="20" symbolic="YES" id="9KE-bP-0Yi"/>
|
|
||||||
<constraint firstItem="MUP-Im-g6c" firstAttribute="top" secondItem="se5-gp-TjO" secondAttribute="top" constant="27" id="BkF-ED-Uva"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="MUP-Im-g6c" secondAttribute="trailing" constant="20" symbolic="YES" id="E0U-Vh-g3t"/>
|
|
||||||
<constraint firstItem="MUP-Im-g6c" firstAttribute="trailing" secondItem="qCN-8Z-3x3" secondAttribute="trailing" id="TqZ-q6-quu"/>
|
|
||||||
<constraint firstItem="MUP-Im-g6c" firstAttribute="leading" secondItem="se5-gp-TjO" secondAttribute="leading" constant="20" symbolic="YES" id="WXt-cJ-HaW"/>
|
|
||||||
<constraint firstItem="3ev-ns-FKY" firstAttribute="top" secondItem="qCN-8Z-3x3" secondAttribute="top" id="b4O-RW-K56"/>
|
|
||||||
<constraint firstItem="MUP-Im-g6c" firstAttribute="leading" secondItem="3ev-ns-FKY" secondAttribute="leading" id="g8i-I5-2Dw"/>
|
|
||||||
<constraint firstItem="3ev-ns-FKY" firstAttribute="bottom" secondItem="qCN-8Z-3x3" secondAttribute="bottom" id="ktC-2I-aWz"/>
|
|
||||||
<constraint firstItem="qCN-8Z-3x3" firstAttribute="leading" secondItem="3ev-ns-FKY" secondAttribute="trailing" constant="8" symbolic="YES" id="opE-OC-8Dh"/>
|
|
||||||
</constraints>
|
|
||||||
</view>
|
|
||||||
<connections>
|
|
||||||
<outlet property="delegate" destination="-2" id="0bl-1N-AYu"/>
|
|
||||||
</connections>
|
|
||||||
<point key="canvasLocation" x="284" y="176.5"/>
|
|
||||||
</window>
|
|
||||||
</objects>
|
|
||||||
</document>
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; };
|
5B09307628B6FC3B0021F8C5 /* shortcuts.html in Resources */ = {isa = PBXBuildFile; fileRef = 5B09307828B6FC3B0021F8C5 /* shortcuts.html */; };
|
||||||
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 */; };
|
5B2CA1E62B130869002634EE /* vChewingFactoryDatabase.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = 5B2CA1E52B130869002634EE /* vChewingFactoryDatabase.sqlite */; };
|
||||||
5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */; };
|
5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */; };
|
||||||
5B40113928D7050D00A9D4CB /* Shared in Frameworks */ = {isa = PBXBuildFile; productRef = 5B40113828D7050D00A9D4CB /* Shared */; };
|
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 = "<group>"; };
|
5B09307A28B6FC400021F8C5 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = en; path = en.lproj/shortcuts.html; sourceTree = "<group>"; };
|
||||||
5B09307B28B6FC410021F8C5 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = ja; path = ja.lproj/shortcuts.html; sourceTree = "<group>"; };
|
5B09307B28B6FC410021F8C5 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; lineEnding = 0; name = ja; path = ja.lproj/shortcuts.html; sourceTree = "<group>"; };
|
||||||
5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
5B0C5EDF27C7D9870078037C /* dataCompiler.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; fileEncoding = 4; indentWidth = 2; lineEnding = 0; path = dataCompiler.swift; sourceTree = "<group>"; tabWidth = 2; usesTabs = 0; };
|
||||||
5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = frmClientListMgr.xib; sourceTree = "<group>"; };
|
|
||||||
5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CtlClientListMgr.swift; sourceTree = "<group>"; };
|
|
||||||
5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = "<group>"; };
|
5B18BA6F27C7BD8B0056EB19 /* LICENSE-CHS.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "LICENSE-CHS.txt"; sourceTree = "<group>"; };
|
||||||
5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
5B18BA7027C7BD8B0056EB19 /* Makefile */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||||
5B18BA7127C7BD8B0056EB19 /* README-CHS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHS.md"; sourceTree = "<group>"; };
|
5B18BA7127C7BD8B0056EB19 /* README-CHS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "README-CHS.md"; sourceTree = "<group>"; };
|
||||||
|
@ -293,7 +289,6 @@
|
||||||
5B62A33A27AE7C7500A19448 /* WindowControllers */ = {
|
5B62A33A27AE7C7500A19448 /* WindowControllers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5B0EF55E28CDBF8E00F8F7CE /* CtlClientListMgr.swift */,
|
|
||||||
5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */,
|
5B30BF272944867800BD87A9 /* CtlRevLookupWindow.swift */,
|
||||||
);
|
);
|
||||||
path = WindowControllers;
|
path = WindowControllers;
|
||||||
|
@ -302,7 +297,6 @@
|
||||||
5B62A33B27AE7C7F00A19448 /* WindowNIBs */ = {
|
5B62A33B27AE7C7F00A19448 /* WindowNIBs */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5B0EF55C28CDBF7100F8F7CE /* frmClientListMgr.xib */,
|
|
||||||
6A187E2816004C5900466B2E /* MainMenu.xib */,
|
6A187E2816004C5900466B2E /* MainMenu.xib */,
|
||||||
);
|
);
|
||||||
path = WindowNIBs;
|
path = WindowNIBs;
|
||||||
|
@ -597,7 +591,6 @@
|
||||||
5B70F4EC2A0BE900005EA8C4 /* MenuIcon-TCVIM@2x.png in Resources */,
|
5B70F4EC2A0BE900005EA8C4 /* MenuIcon-TCVIM@2x.png in Resources */,
|
||||||
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */,
|
5BF9DA2828840E6200DBD48E /* template-exclusions.txt in Resources */,
|
||||||
5B7DA80328BF6BC600D7B2AD /* fixinstall.sh in Resources */,
|
5B7DA80328BF6BC600D7B2AD /* fixinstall.sh in Resources */,
|
||||||
5B0EF55D28CDBF7100F8F7CE /* frmClientListMgr.xib in Resources */,
|
|
||||||
5B70F4E92A0BE900005EA8C4 /* MenuIcon-TCVIM.png in Resources */,
|
5B70F4E92A0BE900005EA8C4 /* MenuIcon-TCVIM.png in Resources */,
|
||||||
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */,
|
5BBBB76027AED54C0023B93A /* Fart.m4a in Resources */,
|
||||||
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
|
6A2E40F6253A69DA00D1AE1D /* Images.xcassets in Resources */,
|
||||||
|
@ -727,7 +720,6 @@
|
||||||
files = (
|
files = (
|
||||||
D427F76C278CA2B0004A2160 /* AppDelegateImpl.swift in Sources */,
|
D427F76C278CA2B0004A2160 /* AppDelegateImpl.swift in Sources */,
|
||||||
D47B92C027972AD100458394 /* main.swift in Sources */,
|
D47B92C027972AD100458394 /* main.swift in Sources */,
|
||||||
5B0EF55F28CDBF8E00F8F7CE /* CtlClientListMgr.swift in Sources */,
|
|
||||||
5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */,
|
5B30BF282944867800BD87A9 /* CtlRevLookupWindow.swift in Sources */,
|
||||||
5BB802DA27FABA8300CF1C19 /* SessionCtl_Menu.swift in Sources */,
|
5BB802DA27FABA8300CF1C19 /* SessionCtl_Menu.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue