// // KMPrintWindowController.swift // PDF Reader Pro // // Created by lizhe on 2022/12/8. // import Cocoa import PDFKit var sizeController: KMPDFPrintManageWindowController? var bookletWindowController: KMPDFBookletWindowController? var multiplePrintWindowController: KMPDFMultiplePrintWindowController? var posterPrintWindowController: KMPDFPosterPrintWindowController? typealias KMPrintWindowControllerPrintTypeChange = (_ controller: KMPrintWindowController, _ type: KMPrintModelType) -> Void class KMPrintWindowController: KMBaseWindowController, NetServiceBrowserDelegate { @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var preview: KMPrintPreviewView! @IBOutlet weak var chooseView: KMPrintChooseView! @IBOutlet weak var settingView: KMPrintSettingView! @IBOutlet weak var bottomView: KMPrintBottomView! var tempPDFDocument: PDFDocument? var password: String = "" { didSet { self.preview.password = password self.presenter.password = password } } var isPrintPreView: Bool = true { didSet { self.preview.isPrintPreView = isPrintPreView } } var changeTypeAction: KMPrintWindowControllerPrintTypeChange? var chooseData: KMPrintModel = KMPrintModel() { didSet { self.reloadData() } } var inputType: DataNavigationViewButtonActionType? var presenter: KMPrintPresenter = KMPrintPresenter() var printType: KMPrintModelType = .size { didSet { self.chooseData.page.operation.type = printType self.reloadData() } } 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.chooseData, document: pdfDocument!) // } // } // } var inputDocument: CPDFDocument? { didSet { pdfDocument = inputDocument password = inputDocument?.password ?? "" // self.chooseView.inputData = URL(string: "") if pdfDocument != nil { self.preview.pdfDocument = PDFDocument(url: pdfDocument!.documentURL) self.presenter.initPresenter(delegate: self, data: self.chooseData, 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() } override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) { if appearance == .darkAqua { self.window?.contentView?.layer?.backgroundColor = NSColor.init(hex: "#26282B").cgColor } else { self.window?.contentView?.layer?.backgroundColor = NSColor.white.cgColor } } func setup() { self.window?.contentView?.wantsLayer = true self.interfaceThemeDidChanged(self.window?.appearance?.name ?? .aqua) self.titleLabel.font = NSFont.SFProTextSemiboldFont(16.0) self.titleLabel.textColor = KMAppearance.Layout.h0Color() self.titleLabel.stringValue = NSLocalizedString("Print", comment: "") self.bottomView.delegate = self self.chooseView.delegate = self self.settingView.pageSettingChange = { [unowned self] view, model in self.chooseData = model self.presenter.printData = model } self.settingView.printSettingChange = { [unowned self] view, model in self.chooseData = model self.presenter.printData = model } } func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) { KMPrint(service) // output: local. _ipp._tcp. RICOH imagio MP C3302 [002673499B5F] -1 } func reloadData() { guard let bottomView = bottomView else { return } self.preview.model = chooseData self.settingView.printModel = chooseData self.bottomView.type = printType self.settingView.type = printType } } //MARK: 打开文件 extension KMPrintWindowController { /** @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 showNewPrintWindowControll(inputDocument: CPDFDocument?, inputType: DataNavigationViewButtonActionType = .Print, inputPageRange: KMPrintPageRange, printType: KMPrintModelType = .size) { //订阅 if !IAPProductsManager.default().isAvailableAllFunction() && printType != .size { KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) return } if inputDocument != nil { if !inputDocument!.allowsCopying || !inputDocument!.allowsPrinting { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } guard let pdfDocument = PDFDocument(url: inputDocument!.documentURL) else { return } } guard let pdfDocument = PDFDocument(url: inputDocument!.documentURL) else { return } switch printType { case .size: sizeController = KMPDFPrintManageWindowController.init(pdfDocument: pdfDocument, currentPage: pdfDocument.page(at: 0)) { document in KMPrintWindowController.openPrintView(document: document) } NSWindow.currentWindow().beginSheet(sizeController!.window!) case .poster: posterPrintWindowController = KMPDFPosterPrintWindowController.init(pdfDocument: pdfDocument) NSWindow.currentWindow().beginSheet(posterPrintWindowController!.window!) case .multipage: multiplePrintWindowController = KMPDFMultiplePrintWindowController.init(pdfDocument: pdfDocument) NSWindow.currentWindow().beginSheet(multiplePrintWindowController!.window!) case .pamphlet: bookletWindowController = KMPDFBookletWindowController.init(document: pdfDocument) NSWindow.currentWindow().beginSheet(bookletWindowController!.window!) default: break } // let printWindowController: KMPrintWindowController = KMPrintWindowController.init(windowNibName: "KMPrintWindowController") // // printWindowController.printType = printType // switch printType { // case .size: // printWindowController.window?.contentMinSize = CGSize(width: 600, height: 500) // printWindowController.window?.contentMaxSize = CGSize(width: 600, height: 500) // printWindowController.window?.setFrame(NSRect(x: 0, y: 0, width: 600, height: 500), display: true) // case .poster: // printWindowController.window?.contentMinSize = CGSize(width: 800, height: 500) // printWindowController.window?.contentMaxSize = CGSize(width: 800, height: 500) // printWindowController.window?.setFrame(NSRect(x: 0, y: 0, width: 800, height: 500), display: true) // case .multipage: // printWindowController.window?.contentMinSize = CGSize(width: 800, height: 700) // printWindowController.window?.contentMaxSize = CGSize(width: 800, height: 700) // printWindowController.window?.setFrame(NSRect(x: 0, y: 0, width: 800, height: 700), display: true) // case .pamphlet: // printWindowController.window?.contentMinSize = CGSize(width: 800, height: 600) // printWindowController.window?.contentMaxSize = CGSize(width: 800, height: 600) // printWindowController.window?.setFrame(NSRect(x: 0, y: 0, width: 800, height: 600), display: true) // default: // break // } // // NSWindow.currentWindow().beginSheet(printWindowController.window!) // if inputDocument != nil { // printWindowController.inputDocument = inputDocument // } // // printWindowController.inputType = inputType // printWindowController.inputPageRange = inputPageRange } static func showPrintWindowControll(inputData: URL?, inputDocument: AnyObject?, inputType: DataNavigationViewButtonActionType = .Print, inputPageRange: KMPrintPageRange) { var document: PDFDocument? let filePath = KMPrintPresenter.fetchSaveFilePath("") var password: String = "" if inputDocument != nil { // 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 document != nil { //页面选取 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 inputDocument != nil { document?.unlock(withPassword: password) } if (inputDocument!.allowsPrinting == false) { KMPasswordInputWindow.openWindow(window: NSApp.mainWindow!, type: .owner, url: (inputDocument!.documentURL)!) { result , resultPassword in if (result == .cancel) { return } document!.unlock(withPassword: resultPassword ?? "") KMPrintWindowController.openPrintView(document: document) } return } else { KMPrintWindowController.openPrintView(document: document) } } } static func openPrintView(document: PDFDocument?) { guard let document = document else { return } if (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) ?? NSPrintOperation() } 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) } } static func openPrinter(document: PDFDocument) { let printInfo = NSPrintInfo.shared let printOperation: NSPrintOperation = document.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: true)! printOperation.showsPrintPanel = true //是否弹出打印机设置界面 printOperation.run() } } //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()) } static func cpdf_printImage(image: NSImage) { let pdfDocument : PDFDocument = PDFDocument() let newpage : PDFPage = PDFPage(image: image)! pdfDocument.insert(newpage, at: 0) KMPrintWindowController.openPrintView(document: pdfDocument) } } 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") // guard let url = self.presenter.printData.url else { return } guard let document = self.tempPDFDocument else { return } // guard let url = self.tempPDFDocument?.documentURL else { return } // let document = CPDFDocument(url: url) // NSPanel.savePanel_pdf_success(self.window!, document: document) { result in // NSWorkspace.shared.selectFile(result.path, inFileViewerRootedAtPath: "") // } // let savePanel = NSSavePanel() savePanel.allowedFileTypes = ["pdf"] savePanel.beginSheetModal(for: NSWindow.currentWindow(), completionHandler: { result in if result != .OK { // completion(result, nil) } else { document.write(to: savePanel.url!) NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "") // completion(result, success ? savePanel.url! : nil) } }) } func printerAction() { KMPrint("调用打印机打印") guard let url = self.presenter.printData.url else { return } let document = PDFDocument.init(url: 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("打印机直接打印") // guard let url = self.presenter.printData.url else { return } // let document = PDFDocument.init(url: url) guard let document = self.tempPDFDocument else { return } let printInfo = NSPrintInfo.shared let printOperation: NSPrintOperation = document.printOperation(for: printInfo, scalingMode: .pageScaleNone, autoRotate: true)! printOperation.showsPrintPanel = true //是否弹出打印机设置界面 printOperation.run() } func posterAction() { self.changeTypeAction?(self, .poster) self.cancelAction() KMPrintWindowController.showNewPrintWindowControll(inputDocument: self.pdfDocument, inputPageRange: KMPrintPageRange(), printType: .poster) } func multipageAction() { self.changeTypeAction?(self, .multipage) self.cancelAction() KMPrintWindowController.showNewPrintWindowControll(inputDocument: self.pdfDocument, inputPageRange: KMPrintPageRange(), printType: .multipage) } func bookletAction() { self.changeTypeAction?(self, .pamphlet) self.cancelAction() KMPrintWindowController.showNewPrintWindowControll(inputDocument: self.pdfDocument, inputPageRange: KMPrintPageRange(), printType: .pamphlet) } } 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: PDFDocument) { self.tempPDFDocument = document self.preview.model = self.chooseData if isPrintPreView && self.preview.model?.page.operation.type == .poster { // self.preview.pdfDocument = pdfDocument } else { self.preview.pdfDocument = document } self.preview.updatePosterPreView() } }