// // AutoTestAdvanceSettingView.swift // KdanAuto // // Created by 朱东勇 on 2022/11/25. // import Foundation import AppKit let kItemCountPerRow = 3 public protocol AutoTestAdvanceSettingViewDelegate : NSObjectProtocol { func advanceSettingDidUpdate(_ settingView:NSView?) } class AutoTestAdvanceSettingView : NSView, NSTableViewDataSource, NSTableViewDelegate, TestFileCellViewDelegate { @IBOutlet var _titleLbl : NSTextField! @IBOutlet var _keyScrollView : NSScrollView! @IBOutlet var _keyContentView : NSView! @IBOutlet var _fileList : NSTableView! @IBOutlet var _replaceAllBtn : NSButton! @IBOutlet var _addBtn : NSButton! var _keyViews : NSMutableArray! var _autoTestObj : AutoTest? var _files : [String]! = [] var _appleInterface : Any? var delegate : AutoTestAdvanceSettingViewDelegate? override func awakeFromNib() { self.wantsLayer = true; updateBGColor() _addBtn.isHidden = true; _appleInterface = DistributedNotificationCenter.default().addObserver(forName: Notification.Name("AppleInterfaceThemeChangedNotification"), object: nil, queue: nil) { notification in DispatchQueue.main.async { self.updateBGColor() } } } func isDarkMode() -> Bool { let apperace = NSApplication.shared.effectiveAppearance return apperace.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua } func updateBGColor() { self.wantsLayer = true; if (isDarkMode()) { self.layer?.backgroundColor = NSColor(white: 0.196, alpha: 1).cgColor }else { self.layer?.backgroundColor = NSColor(white: 0.925, alpha: 1).cgColor } // self.layer?.backgroundColor = NSColor(named: "AdvanceBackgrougColor")?.cgColor } // Setter let kCheckBtnDefaultHeight = 25.0 public func getAutoTestObj() -> AutoTest? { return _autoTestObj } public func setAutoTestObj(_ obj:AutoTest?) { _autoTestObj = obj; // Set Title // self.setAccessibilityEnabled((_autoTestObj?.isOriginFileExist() == true && _autoTestObj?.isCheckFileExist() == true)) // _addBtn.isHidden = nil == _autoTestObj; if nil != _autoTestObj { _titleLbl.stringValue = "【"+(_autoTestObj?.fileType() ?? "")+"】"+(_autoTestObj?.name() ?? "") let checkKeys = NSArray(array: _autoTestObj?.keys() ?? []) let selectKeys = NSArray(array: _autoTestObj?.selectedKeys() ?? []) if _keyViews == nil { _keyViews = NSMutableArray() } while (_keyViews.count != checkKeys.count) { if (_keyViews.count > checkKeys.count) { (_keyViews.lastObject as! NSButton).removeFromSuperview() _keyViews.removeLastObject() }else { let checkBtn = NSButton(checkboxWithTitle: "", target: self, action: #selector(keyChecked)) _keyContentView.addSubview(checkBtn); _keyViews.add(checkBtn) } } var height = CGFloat((_keyViews.count + 1)/kItemCountPerRow * (Int(kCheckBtnDefaultHeight) + 5)); // _keyContentView.frame = NSRect(x: 0, y: 0, width: width, height: kTFDefaultHeight) if ((height+28) > _keyScrollView.frame.height) { _keyContentView.setFrameSize(NSSize.init(width: _keyScrollView.frame.width - 28, height: height)) }else { height = _keyScrollView.frame.height - 28 _keyContentView.setFrameSize(NSSize.init(width: _keyScrollView.frame.width - 28, height: height)) } for btn in NSArray(array: _keyViews) { let i = _keyViews.index(of: btn) let checkBtn = btn as! NSButton checkBtn.title = checkKeys[i] as! String; // Update Check Status if selectKeys.contains(checkKeys[i]) { checkBtn.state = .on }else { checkBtn.state = .off } checkBtn.sizeToFit() checkBtn.frame = CGRect.init(x: CGFloat(i % kItemCountPerRow) * _keyContentView.frame.size.width/CGFloat(kItemCountPerRow), y: CGFloat(height - kCheckBtnDefaultHeight), width: checkBtn.frame.width, height: kCheckBtnDefaultHeight) checkBtn.autoresizingMask = .maxXMargin.union(.minYMargin) if i % kItemCountPerRow == (kItemCountPerRow - 1) { height = height - checkBtn.frame.height - 5 } } _keyScrollView.documentView = _keyContentView; _files = DataModel.shared.originFilesFor(String(_autoTestObj?.fileType() ?? ""), type: String(_autoTestObj?.type() ?? "")) _fileList.reloadData() _replaceAllBtn.isEnabled = _autoTestObj!.canUpdateRefImage() }else { _titleLbl.stringValue = "" if _keyViews == nil { _keyViews = NSMutableArray() } while (_keyViews.count != 0) { (_keyViews.lastObject as! NSView).removeFromSuperview() _keyViews.removeLastObject() } _files = [] _fileList.reloadData() _replaceAllBtn.isEnabled = false } } /// IBActionn @IBAction func keyChecked(_ sender:NSButton) { let currentSelectedKeys = NSMutableArray() let checkKeys = NSArray(array: _autoTestObj?.keys() ?? []) for btn in NSArray(array: _keyViews) { let cBtn = btn as! NSButton if cBtn.state == .on { let index = _keyViews.index(of: btn) currentSelectedKeys.add(checkKeys[index]) } } _autoTestObj?.setSelectedKeys(currentSelectedKeys) if delegate != nil { delegate?.advanceSettingDidUpdate(self) } } @IBAction func replaceAllAction(_ sender:NSButton) { if nil != _autoTestObj { _autoTestObj?.updateRefImage() } _fileList.reloadData(); _replaceAllBtn.isEnabled = _autoTestObj!.canUpdateRefImage() } @IBAction func addFileAction(_ sender:NSButton) { // let files = _autoTestObj?.compareFiles() ?? [] // // if nil != files && files.count > 0 { // let compareVC = CompareViewController.shared() // compareVC.setFiles(files) // compareVC.showIn(sender) // } // // return if nil == _autoTestObj { return } let originDirectory = _autoTestObj?.originFileDirectory() let openPanel = NSOpenPanel() openPanel.canChooseFiles = true openPanel.allowsMultipleSelection = true if #available(macOS 11.0, *) { openPanel.allowedContentTypes = [.pdf] } else { openPanel.allowedFileTypes = ["pdf", "PDF"] } openPanel.canChooseDirectories = true let comboBox = NSComboBox.init(frame: NSRect.init(x: 0, y: 0, width: 100, height: 25)) comboBox.removeAllItems() comboBox.addItems(withObjectValues: ["添加超链接", "导入文件"]) comboBox.selectItem(at: 0) openPanel.accessoryView = comboBox; if openPanel.runModal() == NSApplication.ModalResponse.OK { let paths = NSMutableArray() if openPanel.urls.count != 0 { for url in openPanel.urls { var path = url.relativePath if path.lengthOfBytes(using: .utf8) == 0 { path = url.absoluteString } if path.lengthOfBytes(using: .utf8) != 0 { paths.add(path) } } }else { var path = openPanel.url?.relativePath if nil == path { path = openPanel.url?.absoluteString } if nil != path { paths.add(path!) } } for item in NSArray(array: paths) { let path = item as! String if comboBox.indexOfSelectedItem == 0 { createSymbolicLink(path, toDirectory: originDirectory!) }else { copyFile(path, toDirectory: originDirectory!) } } _files = DataModel.shared.originFilesFor(String(_autoTestObj?.fileType() ?? ""), type: String(_autoTestObj?.type() ?? "")) _fileList.reloadData() } } func createSymbolicLink(_ path:String, toDirectory:String) { var isDirectory = ObjCBool(false) if FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) { if isDirectory.boolValue { // 文件夹 let subpaths = try! FileManager.default.subpathsOfDirectory(atPath: path) for subpath in subpaths { if NSString(string: subpath).contains(".DS_Store") { continue } let nPath = NSString(string: path).appendingPathComponent(subpath) var isDirectory = ObjCBool(false) if FileManager.default.fileExists(atPath: nPath, isDirectory: &isDirectory) && isDirectory.boolValue { continue } let resultPath = NSString(string: toDirectory).appendingPathComponent(NSString(string: path).lastPathComponent+"/"+subpath) createSymbolicLink(nPath, toDirectory: NSString(string: resultPath).deletingLastPathComponent) } }else { let resultPath = NSString(string: toDirectory).appendingPathComponent(NSString(string: path).lastPathComponent) let directory = NSString(string: resultPath).deletingLastPathComponent // Create directory for var isDirectory = ObjCBool(false) if !FileManager.default.fileExists(atPath: directory, isDirectory: &isDirectory) || !isDirectory.boolValue { try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true) } if FileManager.default.fileExists(atPath: resultPath) { try? FileManager.default.removeItem(atPath: resultPath) } try? FileManager.default.createSymbolicLink(atPath: resultPath, withDestinationPath: path) } } } func copyFile(_ path:String, toDirectory:String) { let resultPath = NSString(string: toDirectory).appendingPathComponent(NSString(string: path).lastPathComponent) if FileManager.default.fileExists(atPath: path) { let directory = NSString(string: resultPath).deletingLastPathComponent // Create directory for var isDirectory = ObjCBool(false) if !FileManager.default.fileExists(atPath: directory, isDirectory: &isDirectory) || !isDirectory.boolValue { try? FileManager.default.createDirectory(atPath: directory, withIntermediateDirectories: true) } if FileManager.default.fileExists(atPath: resultPath) { try? FileManager.default.removeItem(atPath: resultPath) } try? FileManager.default.copyItem(atPath: path, toPath: resultPath) } } // TableView Delegate func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { let cellView = TestFileCellView.shared() if (_files.count >= row) { let title = _files[row] cellView?.setTitle(title) cellView?._delegate = self if _autoTestObj != nil { cellView?.setNeedReplaceBtn(_autoTestObj!.canUpdateRefImage(title)) }else { cellView?.setNeedReplaceBtn(false) } if (_autoTestObj != nil) { cellView?.set((_autoTestObj!.status() == .Process && _autoTestObj!.convertFiles.contains(title) && !_autoTestObj!.compareFinishedFiles.contains(title))) }else { cellView?.set(false) } if _autoTestObj != nil && (_autoTestObj?.status() == .Finished || _autoTestObj!.compareFinishedFiles.contains(title)) { cellView?.setNeedDegreeBtn(true) cellView?.setDegree((_autoTestObj?.degreeOfFile(title))!) }else { cellView?.setNeedDegreeBtn(false) } } return cellView } func selectionShouldChange(in tableView: NSTableView) -> Bool { return true } func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool { return false } func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool { return false } func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) { } func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) { } func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) { } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { return 30 } func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool { return false } func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat { return tableView.frame.width } func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] { return [] } func tableViewSelectionDidChange(_ notification: Notification) { } // TableView Data Source func numberOfRows(in tableView: NSTableView) -> Int { return _files.count } // TestFileCellViewDelegate func fileCellNeedReplace(_ cell: TestFileCellView, fileName: String) { if (_autoTestObj != nil) { _autoTestObj?.updateRefImage(fileName) } _replaceAllBtn.isEnabled = _autoTestObj!.canUpdateRefImage() _fileList.reloadData() } func fileCellNeedShowReport(_ cell: TestFileCellView, fileName: String, sender:NSButton) { let files = _autoTestObj?.compareFiles(fileName) ?? [] if files.count > 0 { if (_autoTestObj as? StringAutoTest) != nil { var compareVC = StringCompareViewController.shared() compareVC.setFiles(files) let point = sender.convert(CGPoint(x: 0, y: 0), to: self) compareVC.showIn(self, rect: NSRect.init(origin: point, size: sender.frame.size)) }else { let compareVC = CompareViewController.shared() compareVC.setFiles(files) let point = sender.convert(CGPoint(x: 0, y: 0), to: self) compareVC.showIn(self, rect: NSRect.init(origin: point, size: sender.frame.size)) } } } func fileCellNeedShowInFinder(_ cell:TestFileCellView, fileName:String, type:TestFileType) { var nFileName = NSString(string: fileName) var directory = _autoTestObj?.originFileDirectory() if (type == .Result) { nFileName = NSString(string: nFileName.deletingPathExtension).appendingPathExtension(_autoTestObj?.extention() ?? "")! as NSString directory = _autoTestObj?.resultFileDirectory() }else if (type == .Compare) { nFileName = NSString(string: nFileName.deletingPathExtension).appendingPathExtension(_autoTestObj?.extention() ?? "")! as NSString directory = _autoTestObj?.checkFileDirectory() } var path = NSString(string: directory!).appendingPathComponent(nFileName as String); if (FileManager.default.fileExists(atPath: path)) { NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: path)]) }else { path = NSString(string: path).deletingPathExtension.appending(".jpg") if (FileManager.default.fileExists(atPath: path)) { NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: path)]) }else { NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: NSString(string: path).deletingLastPathComponent)]) } } } func fileCellNeedDelete(_ cell:TestFileCellView, fileName:String) { let originDirectory = _autoTestObj?.originFileDirectory() let path = NSString(string: originDirectory!).appendingPathComponent(fileName); FileConverter.shared().cancelTaskForSrcPath(path); try? FileManager.default.removeItem(atPath: path); let index = _files.firstIndex(of: fileName) if (index != NSNotFound) { _files.remove(at: index!) _fileList.reloadData() } } func fileCellNeedCancelConvertTask(_ cell:TestFileCellView, fileName:String) { let originDirectory = _autoTestObj?.originFileDirectory() let path = NSString(string: originDirectory!).appendingPathComponent(fileName); FileConverter.shared().cancelTaskForSrcPath(path); } }