// // KMNOutlineHanddler.swift // PDF Reader Pro // // Created by User-Tangchao on 2024/11/12. // import Cocoa @objc protocol KMNOutlineHanddlerDelegate: NSObjectProtocol { @objc optional func handdler(_ handdler: KMNOutlineHanddler, didAdd info: [String : Any]?) @objc optional func handdler(_ handdler: KMNOutlineHanddler, didRemove info: [String : Any]?) @objc optional func handdler(_ handdler: KMNOutlineHanddler, didRename outline: CPDFOutline?, info: [String : Any]?) @objc optional func handdler(_ handdler: KMNOutlineHanddler, didChangeLocation outline: CPDFOutline?, info: [String : Any]?) @objc optional func handdler(_ handdler: KMNOutlineHanddler, didMove outline: CPDFOutline?, info: [String : Any]?) } class KMNOutlineHanddler: NSObject { weak var pdfView: CPDFView? weak var delegate: KMNOutlineHanddlerDelegate? var document: CPDFDocument? { get { return pdfView?.document } } var currentPageIndex: Int { get { return pdfView?.currentPageIndex ?? 0 } } // Private Methods private func _showAlert(style: NSAlert.Style = .critical, message: String, informative: String = "", buttons: [String] = []) -> NSApplication.ModalResponse { let alert = NSAlert() alert.alertStyle = style alert.messageText = message alert.informativeText = informative for title in buttons { alert.addButton(withTitle: title) } return alert.runModal() } // Pulick Methods func pageCount() -> Int { return Int(self.document?.pageCount ?? 0) } func isLocked() -> Bool { return self.document?.isLocked ?? true } func outlineRoot() -> CPDFOutline? { return self.document?.outlineRoot() } func setNewOutlineRoot() -> CPDFOutline? { return self.document?.setNewOutlineRoot() } func currentSelection() -> CPDFSelection? { return pdfView?.currentSelection } func currentDestination() -> CPDFDestination? { return pdfView?.currentDestination } func canUndo() -> Bool { return pdfView?.undoManager?.canUndo ?? false } func canRedo() -> Bool { return pdfView?.undoManager?.canRedo ?? false } func undo() { if canUndo() { pdfView?.undoManager?.undo() } } func redo() { if canRedo() { pdfView?.undoManager?.redo() } } func selectOutline(_ outline: CPDFOutline?) { guard let ol = outline else { return } if let dest = ol.destination { pdfView?.go(to: dest) } else if let act = ol.action { pdfView?.perform(act) } else { _ = _showAlert(style: .informational, message: KMLocalizedString("The target page is invalid, please relocate it.")) } } func addOutline(outlineItems: [KMBOTAOutlineItem]) { var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems tempOutlineItems.sort(){$0.toIndex < $1.toIndex} for outlineItem in tempOutlineItems { if outlineItem.outline.label != nil { outlineItem.parent?.outline.insertChild(outlineItem.outline, at: UInt(outlineItem.toIndex)) } else { let outline = outlineItem.parent?.outline.insertChild(at: UInt(outlineItem.toIndex)) outline?.label = outlineItem.label outline?.destination = outlineItem.destination outlineItem.outline = outline! } outlineItem.parent?.children.insert(outlineItem, at: outlineItem.toIndex) } delegate?.handdler?(self, didAdd: ["data": tempOutlineItems]) pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in self?.deleteOutline(outlineItems: tempOutlineItems) } } func deleteOutline(outlineItems: [KMBOTAOutlineItem]) { var tempOutlineItems: [KMBOTAOutlineItem] = outlineItems tempOutlineItems.sort(){$0.toIndex > $1.toIndex} for outlineItem in tempOutlineItems { outlineItem.outline.removeFromParent() let index = outlineItem.parent?.children.firstIndex(of: outlineItem) outlineItem.toIndex = index! outlineItem.parent?.children.removeObject(outlineItem) } delegate?.handdler?(self, didRemove: ["data" : tempOutlineItems]) pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in self?.addOutline(outlineItems: tempOutlineItems) } } func renamePDFOutline(outlineItem: KMBOTAOutlineItem!, label: String) { if outlineItem.outline.label == label { return } let temp: String = outlineItem.outline.label outlineItem.outline.label = label delegate?.handdler?(self, didRename: outlineItem.outline, info: ["data" : outlineItem]) pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in self?.renamePDFOutline(outlineItem: outlineItem, label: temp) } } func changeLocation(outlineItem: KMBOTAOutlineItem, destination: CPDFDestination) { let temp = outlineItem.outline.destination outlineItem.outline.destination = CPDFDestination(document: destination.document, pageIndex: destination.pageIndex, at: destination.point, zoom: destination.zoom) delegate?.handdler?(self, didChangeLocation: outlineItem.outline, info: ["data" : outlineItem]) pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in if let data = temp { self?.changeLocation(outlineItem: outlineItem, destination: data) } } } func moveOutline(outlineItem: KMBOTAOutlineItem, index: NSInteger, parent: KMBOTAOutlineItem!) { // let tempOutlineView = self.BOTAOutlineView! let indexTemp = outlineItem.outline.index let parentTemp = outlineItem.parent //元数据移除 outlineItem.outline.removeFromParent() parent.outline.insertChild(outlineItem.outline, at: UInt(index)) delegate?.handdler?(self, didMove: outlineItem.outline, info: ["data" : outlineItem, "parent" : parent, "index" : index]) pdfView?.undoManager?.registerUndo(withTarget: self) { [weak self] targetType in self?.moveOutline(outlineItem: outlineItem, index: NSInteger(indexTemp), parent: parentTemp) } } }