// // KMHeaderFooterPreviewController.swift // PDF Reader Pro // // Created by tangchao on 2022/12/26. // import Cocoa /// 页眉页脚 预览控制器 class KMHeaderFooterPreviewController: KMWatermarkAdjectivePreViewBaseController { override func viewDidLoad() { super.viewDidLoad() let itemTitles = [[NSLocalizedString("Add HeaderAndFooter", comment: ""), NSLocalizedString("Delete HeaderAndFooter", comment: "")], [NSLocalizedString("Batch", comment: "")]] var itemModels: Array> = [] for items in itemTitles { var array: Array = [] for title in items { let model = KMWatermarkAdjectiveTopBarItemModel() model.iconName = "" model.itemTitle = title array.append(model) } itemModels.append(array) } self.topBarView.initItemData(itemArrays: itemModels) self.topBarView.selectTopItem(index: 0) let preView: KMWatermarkPDFView_OC = KMWatermarkPDFView_OC() self.preView = preView self.preView.frame = self.preViewBox.contentView!.bounds self.preView.autoresizingMask = [.width, .height] self.preViewBox.contentView?.addSubview(self.preView) self.preView.setDisplay(.singlePage) let controller = KMHeaderFooterPropertyMainController() controller.view.frame = self.rightBox.contentView!.bounds controller.view.autoresizingMask = [.width, .height] self.right_gotoViewController(viewController: controller) controller.modelDidChange = { [weak self] model in if (model == nil || (model as! KMHeaderFooterObject).hasVaild == false) { self!.topBarView.isCanApply(can: false) self!.model = nil } else { self!.topBarView.isCanApply(can: true) self!.model = model self?.model?.pageCount = Int((self?.preView.document.pageCount)!) } (self?.preView as! KMWatermarkPDFView_OC).model = model } } override func viewDidAppear() { super.viewDidAppear() (self.rightViewController as! KMHeaderFooterPropertyMainController).pageCount = Int(self.preView.document.pageCount) } override func topItemClick(index: Int) { if (index == 0) { /// 添加 return } if (index == 2) { /// 批量 // KMBatchWindowController.openFile(nil, .HeaderAndFooter) return } if (index == 2) { /// 批量 // KMBatchWindowController.openFile(nil, .HeaderAndFooter) return } /// 移除 self.beginLoading() self.deleteHeaderFooter(toPath: self.preView.document.documentURL.path) { result in self.endLoading() if (result) { DispatchQueue.main.async { self.preView.document = CPDFDocument(url: self.preView.document.documentURL) } } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Failure", comment: "") alert.runModal() } } } override func applyAction() { if (self.model == nil) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Failure", comment: "") alert.runModal() return } self.beginLoading() self.addHeaderFooter(model: self.model! as! KMHeaderFooterObject, toPath: self.preView.document.documentURL.path, completion: { result in DispatchQueue.main.async { self.preView.layoutDocumentView() self.preView.setNeedsDisplayForVisiblePages() } self.endLoading() if (result) { guard let callback = self.itemClick else { return } callback(1, nil) } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Failure", comment: "") alert.runModal() } }) } private func addHeaderFooter(model: KMHeaderFooterObject, toPath: String, completion: @escaping (_ result: Bool) -> ()) { DispatchQueue.global().async { let document: CPDFDocument = self.preView.document var property = document.headerFooter() var fontSize = 0.0 var fontName: String = "" switch model.textFont { case .font(name: let name, size: let size): fontSize = size fontName = name break default: break } let font = NSFont.boldSystemFont(ofSize:fontSize) let style = NSMutableParagraphStyle() style.alignment = .center style.lineBreakMode = .byCharWrapping let size: NSSize = "text".boundingRect(with: NSSize(width: 1000, height: 1000), options: NSString.DrawingOptions(rawValue: 3), attributes: [NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style]).size property?.margin = NSEdgeInsetsMake(max(CGFloat(model.topMargin)-size.height, 0), CGFloat(model.leftMargin), max(CGFloat(model.bottomMargin)-size.height, 0), CGFloat(model.rightMargin)) let strings = KMHeaderFooterPreviewController.parseModel(model: model, pageCount: Int(self.preView.document.pageCount)) var count: Int = 0 var color: NSColor! switch model.textColor { case .color(red: let red, green: let green, blue: let blue, alpha: let alpha): color = NSColor(red: red, green: green, blue: blue, alpha: alpha) default: break } if (color == nil) { color = NSColor.black } for text in strings { property?.setText(text, at: UInt(count)) property?.setTextColor(color, at: UInt(count)) property?.setFontSize(fontSize, at: UInt(count)) property?.setFontName(fontName, at: UInt(count)) count += 1 } let pagesString = self.findPagesString(model) if (pagesString.isEmpty) { property?.pageString = "0-\(document.pageCount-1)" } else { property?.pageString = pagesString } property?.update() /// 保存到临时路径 let documentPath = NSTemporaryDirectory() let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)" if (FileManager.default.fileExists(atPath: tempPath)) { try?FileManager.default.removeItem(atPath: tempPath) } let result = document.write(to: URL(fileURLWithPath: tempPath)) if (result) { if (FileManager.default.fileExists(atPath: toPath)) { try?FileManager.default.removeItem(atPath: toPath) } try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath) } else { try?FileManager.default.removeItem(atPath: tempPath) } DispatchQueue.main.async { completion(result) } } } func deleteHeaderFooter(toPath: String, completion: @escaping (_ result: Bool) -> ()) { if (self.preView.document.allowsPrinting == false || self.preView.document.allowsCopying == false) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This PDF document's user permissions does not allow modifying, content copying and printing.", comment: "") alert.runModal() completion(false) return } DispatchQueue.global().async { let document: CPDFDocument = self.preView.document var property = document.headerFooter() property?.clear() /// 保存到临时路径 let documentPath = NSTemporaryDirectory() let tempPath: String = "\(documentPath)/\(toPath.lastPathComponent)" if (FileManager.default.fileExists(atPath: tempPath)) { try?FileManager.default.removeItem(atPath: tempPath) } let result = document.write(to: URL(fileURLWithPath: tempPath)) if (result) { if (FileManager.default.fileExists(atPath: toPath)) { try?FileManager.default.removeItem(atPath: toPath) } try?FileManager.default.moveItem(atPath: tempPath, toPath: toPath) } else { try?FileManager.default.removeItem(atPath: tempPath) } DispatchQueue.main.async { completion(result) } } } static func parseModel(model: KMHeaderFooterObject, pageCount: Int) -> [String] { var topLeftString: String = "" if (!model.topLeftString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topLeftString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) topLeftString = string } var topCenterString: String = "" if (!model.topCenterString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topCenterString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) topCenterString = string } var topRightString: String = "" if (!model.topRightString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.topRightString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) topRightString = string } var bottomLeftString: String = "" if (!model.bottomLeftString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomLeftString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) bottomLeftString = string } var bottomCenterString: String = "" if (!model.bottomCenterString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomCenterString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) bottomCenterString = string } var bottomRightString: String = "" if (!model.bottomRightString.isEmpty) { var string = KMWatermarkAdjectiveTools.parsePageFormat(formatString: model.bottomRightString, startPage: model.startString, pageCount: "\(pageCount)") string = KMWatermarkAdjectiveTools.parseDateFormat(formatString: string) bottomRightString = string } return [topLeftString, topCenterString, topRightString, bottomLeftString, bottomCenterString, bottomRightString] } }