// // KMPrintWindowController.swift // PDF Master // // Created by lizhe on 2022/12/8. // import Cocoa import PDFKit class KMPrintWindowController: NSWindowController, NetServiceBrowserDelegate { @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var preview: KMPrintPreviewView! @IBOutlet weak var chooseView: KMPrintChooseView! @IBOutlet weak var bottomView: KMPrintBottomView! var pdfDocument: CPDFDocument? = nil var chooseData: KMPrintModel = KMPrintModel() var inputType: DataNavigationViewButtonActionType? var presenter: KMPrintPresenter = KMPrintPresenter() var inputPageRange: KMPrintPageRange = KMPrintPageRange() { didSet { self.chooseView.inputPageRange = inputPageRange self.preview.toPageIndex(UInt(inputPageRange.selectPages.first ?? 0)) } } var inputData: URL? { didSet { let pdfDocument = CPDFDocument.init(url: inputData) self.chooseView.inputData = inputData if pdfDocument != nil { self.preview.pdfDocument = pdfDocument self.pdfDocument = pdfDocument self.presenter.initPresenter(delegate: self, data: self.chooseView.outputData, document: pdfDocument!) } } } var inputDocument: CPDFDocument? { didSet { pdfDocument = inputDocument self.chooseView.inputData = URL(string: "") if pdfDocument != nil { self.preview.pdfDocument = pdfDocument self.presenter.initPresenter(delegate: self, data: self.chooseView.outputData, document: pdfDocument!) } } } deinit { KMPrint("KMImageToPDFWindowController 释放") } override func windowDidLoad() { super.windowDidLoad() // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. self.window?.title = "Image to PDF" self.setup() self.reloadData() } func setup() { self.window?.contentView?.wantsLayer = true self.window?.contentView?.layer?.backgroundColor = NSColor.km_init(hex: "#FFFFFF").cgColor self.titleLabel.font = NSFont.SFProTextSemiboldFont(16.0) self.titleLabel.textColor = NSColor.km_init(hex: "#252629") self.titleLabel.stringValue = NSLocalizedString("Print", comment: "") self.bottomView.delegate = self self.chooseView.delegate = self } func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) { KMPrint(service) // output: local. _ipp._tcp. RICOH imagio MP C3302 [002673499B5F] -1 } func reloadData() { } //MARK: 打开文件 /** @abstract 选取文件跳转打印界面 @param window 文档地址 @param pageRange 打印范围 */ static func openFiles(window: NSWindow, pageRange: KMPrintPageRange = KMPrintPageRange()) { KMBatchProcessingView.openfiles(window: window) { openPanel in // openPanel.title = "选择图片" openPanel.canChooseDirectories = false openPanel.canChooseFiles = true openPanel.allowsMultipleSelection = false openPanel.allowedFileTypes = KMOCRModel.supportedTypes() } completion: { (panel ,data) in if data.count != 0 { KMPrintWindowController.openFile(inputData: data.first, inputPageRange: pageRange) } } } /** @abstract 打印界面显示 @param inputData 传入URL @param inputType 入口类型 @param inputPageRange 页面范围,默认全部 */ static func openFile(inputData: URL?, inputType: DataNavigationViewButtonActionType = .Print, inputPageRange: KMPrintPageRange = KMPrintPageRange()) { KMPrintWindowController.showPrintWindowControll(inputData: inputData, inputDocument: nil, inputType: inputType,inputPageRange: inputPageRange) } /** @abstract 打印界面显示 @param inputDocument 传入document @param inputType 入口类型 默认print @param inputPageRange 页面范围,默认全部 */ static func openDocument(inputDocument: CPDFDocument?, inputType: DataNavigationViewButtonActionType = .Print, inputPageRange: KMPrintPageRange) { KMPrintWindowController.showPrintWindowControll(inputData: nil, inputDocument: inputDocument, inputType: inputType,inputPageRange: inputPageRange) } static func showPrintWindowControll(inputData: URL?, inputDocument: AnyObject?, inputType: DataNavigationViewButtonActionType = .Print, inputPageRange: KMPrintPageRange) { // if (1) { // let printWindowController: KMPrintWindowController = KMPrintWindowController.init(windowNibName: "KMPrintWindowController") // NSApp.mainWindow?.beginCriticalSheet(printWindowController.window!) // if inputDocument != nil { // printWindowController.inputDocument = inputDocument // } // // if inputData != nil { // printWindowController.inputData = inputData // } // printWindowController.inputType = inputType // printWindowController.inputPageRange = inputPageRange // } else { var document: PDFDocument? let filePath = KMPrintPresenter.fetchSaveFilePath("") var password: String = "" if inputDocument != nil { if inputDocument is CPDFDocument { let success = inputDocument?.writeDecrypt(to: URL(fileURLWithPath: filePath)) password = inputDocument?.password ?? "" if success != nil { document = PDFDocument(url: URL(fileURLWithPath: filePath))! } } else if inputDocument is PDFDocument { document = inputDocument as? PDFDocument } } if inputData != nil { document = PDFDocument.init(url: inputData!)! } //页面选取 if ((inputPageRange.type == .currentPage || inputPageRange.type == .custom) && inputPageRange.selectPages.count != 0) { let printPresent = KMPrintPresenter() let filePath = KMPrintPresenter.fetchSaveFilePath("") let paperSize = (document?.page(at: 0)?.bounds(for: .cropBox).size) ?? CGSizeZero let context: CGContext = printPresent.createContext(filePath, paperSize) var pages: [PDFPage] = [] for index in inputPageRange.selectPages { let page = document?.page(at: index) if page != nil { pages.append(page!) } } for drawPage in pages { context.beginPDFPage(nil) context.saveGState() var pageSize = drawPage.bounds(for: .cropBox).size if (drawPage.rotation == 90 || drawPage.rotation == 270) { let height = pageSize.height pageSize.height = pageSize.width pageSize.width = height } // 检查要自适应的大小是否大于参考矩形的大小 let maxWidth = paperSize.width let maxHeight = paperSize.height var scaledSize = pageSize var ratio = 1.0 if pageSize.width > maxWidth || pageSize.height > maxHeight { let widthRatio = maxWidth / pageSize.width let heightRatio = maxHeight / pageSize.height ratio = min(widthRatio, heightRatio) scaledSize = CGSize(width: pageSize.width * ratio, height: pageSize.height * ratio) } // 计算自适应后的矩形大小和位置 let scaledWidth = scaledSize.width let scaledHeight = scaledSize.height let scaledRect = CGRect(x: (paperSize.width - scaledWidth) / 2, y: (paperSize.height - scaledHeight) / 2, width: scaledWidth, height: scaledHeight) context.translateBy(x: scaledRect.origin.x, y: scaledRect.origin.y) context.scaleBy(x: ratio, y: ratio) drawPage.draw(with: .cropBox, to: context) context.restoreGState() context.endPDFPage() } context.closePDF() document = PDFDocument(url: URL(fileURLWithPath: filePath))! } if document != nil { if inputDocument != nil { document?.unlock(withPassword: password) } if (inputDocument!.allowsPrinting == false) { KMPasswordInputWindow.openWindow(window: NSApp.mainWindow!, type: .owner, url: (inputDocument!.documentURL)!) { result , password in if (result == .cancel) { return } document!.unlock(withPassword: password!) KMPrintWindowController.openPrintView(document: document) } return } else { KMPrintWindowController.openPrintView(document: document) } } } static func openPrintView(document: PDFDocument?) { if (document != nil && document!.allowsPrinting == true) { let printInfo = NSPrintInfo.shared var printOperation: NSPrintOperation = NSPrintOperation() let scalingMode: PDFPrintScalingMode = .pageScaleToFit if document!.responds(to: NSSelectorFromString("printOperationForPrintInfo:scalingMode:autoRotate:")) { printOperation = document!.printOperation(for: printInfo, scalingMode: scalingMode, autoRotate: false)! } printOperation.printPanel.options = [.showsPreview, .showsCopies, .showsOrientation, .showsPageRange, .showsPaperSize, .showsCopies, .showsPrintSelection, .showsScaling] let controller = KMPrintAccessoryController_OC(nibName: "KMPrintAccessoryController_OC", bundle: nil) printOperation.printPanel.addAccessoryController(controller) printOperation.runModal(for: NSApplication.shared.mainWindow!, delegate: self, didRun: nil, contextInfo: nil) } } } //MARK: - Print extension KMPrintWindowController { static func printImage(image: NSImage) { let pdfDocument : PDFDocument = PDFDocument() let newpage : PDFPage = PDFPage(image: image)! pdfDocument.insert(newpage, at: 0) KMPrintWindowController.showPrintWindowControll(inputData: nil, inputDocument: pdfDocument, inputPageRange: KMPrintPageRange()) } } extension NetService { func textRecordField(field: String) -> String? { guard let data = self.txtRecordData(), let field = NetService.dictionary(fromTXTRecord: data)[field] else { return nil } return String(data: field, encoding: String.Encoding.utf8) } } extension KMPrintWindowController: KMPrintBottomViewDelegate { func savePDFAction() { KMPrint("保存PDF") } func printerAction() { KMPrint("调用打印机打印") if self.chooseData.url != nil { let document = PDFDocument.init(url: self.chooseData.url!) let printInfo = NSPrintInfo.shared let printOperation: NSPrintOperation = document!.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: true)! let printPanel = printOperation.printPanel printPanel.options = [.showsOrientation, .showsPageRange, .showsPaperSize, .showsScaling, .showsPreview] printOperation.runModal(for: self.window!, delegate: self, didRun: nil, contextInfo: nil) } } func cancelAction() { KMPrint("cancel") NSApp.mainWindow!.endSheet(self.window!) self.close() // self.window?.orderOut(self) } func printAction() { KMPrint("打印机直接打印") let document = PDFDocument.init(url: self.chooseData.url!) let printInfo = NSPrintInfo.shared let printOperation: NSPrintOperation = document!.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: true)! printOperation.showsPrintPanel = false // printOperation.run() } } extension KMPrintWindowController: KMPrintChooseViewDelegate { func showData(sender: Any, data: KMPrintModel) { self.chooseData = data } func printerChange(sender: Any, data: KMPrintModel) { } func pageSetChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } func pageNumberChange(sender: Any, data: KMPrintModel) { } func blackAndWhiteChange(sender: Any, data: KMPrintModel) { } func printOnBothSidesChange(sender: Any, data: KMPrintModel) { } func pageRangeChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } func printDirectionChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } func printContentChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } func printReverseChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } func printDealModelChange(sender: Any, data: KMPrintModel) { self.chooseData = data self.presenter.reloadData() } } extension KMPrintWindowController: KMPrintPresenterDeleage { func showData(presenter: KMPrintPresenter, document: CPDFDocument) { // self.preview.pdfDocument = document } }