123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- //
- // KMNPageEditViewController.swift
- // PDF Reader Pro
- //
- // Created by 丁林圭 on 2024/10/21.
- //
- import Cocoa
- import KMComponentLibrary
- @objc protocol KMNPageEditViewViewDelegate: AnyObject {
- @objc optional func changeBoundEditViewController(pageEditVC:KMNPageEditViewController)
- @objc optional func changeUndoManagerEditViewController(pageEditVC:KMNPageEditViewController)
- }
- class KMNPageEditViewController: KMNThumbnailBaseViewController {
- override func viewDidLoad() {
- super.viewDidLoad()
-
- self.backViewBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-pdfView")
-
- collectionView.menuClickedAction = { point in
- return self.clickMenu(point: point)
- }
- }
-
- private func clickMenu(point:NSPoint)->NSMenu {
- let copyPages: [CPDFPage] = KMNThumbnailManager.manager.copyPages
- let menu = NSMenu()
- // 根据 clickPoint 创建菜单项
- let copyMenuItem = NSMenuItem(title: KMLocalizedString("Copy"), action: #selector(copyMenuItemAciton), target: self)
- copyMenuItem.keyEquivalent = "c"
-
- let pastMenuItem = NSMenuItem(title: KMLocalizedString("Paste"), action: #selector(pastMenuItemAciton), target: self)
- pastMenuItem.keyEquivalent = "v"
-
- let pastNullMenuItem = NSMenuItem(title: KMLocalizedString("Paste"), action: nil, target: self)
- pastNullMenuItem.keyEquivalent = "v"
-
- let cutMenuItem = NSMenuItem(title: KMLocalizedString("Cut"), action: #selector(cutMenuItemAciton), target: self)
- cutMenuItem.keyEquivalent = "x"
-
- let deleteMenuItem = NSMenuItem(title: KMLocalizedString("Delete"), action: #selector(deleteMenuItemAciton), target: self)
- deleteMenuItem.keyEquivalent = String(Unicode.Scalar(NSBackspaceCharacter)!)
- let rotateLeftMenuItem = NSMenuItem(title: KMLocalizedString("90° CCW"), action: #selector(rotatePageLeftAction), target: self)
- rotateLeftMenuItem.keyEquivalent = "l" // 设置为字母 l
- rotateLeftMenuItem.keyEquivalentModifierMask = [.option, .command] // 设置为 Option + Command
- let rotateRightMenuItem = NSMenuItem(title: KMLocalizedString("90° CW"), action: #selector(rotatePageRightAction), target: self)
- rotateRightMenuItem.keyEquivalent = "r" // 设置为字母 r
- rotateRightMenuItem.keyEquivalentModifierMask = [.option, .command] // 设置为 Option + Command
- let insertFileMenuItem = NSMenuItem(title: KMLocalizedString("Insert File"), action: #selector(insertFromPDFAction), target: self)
- let insertBlankMenuItem = NSMenuItem(title: KMLocalizedString("Insert a Blank Page"), action: #selector(insertFromBlankAction), target: self)
-
- let replaceMenuItem = NSMenuItem(title: KMLocalizedString("Replace"), action: #selector(replacePDFAction), target: self)
-
- let extractMenuItem = NSMenuItem(title: KMLocalizedString("Export"), action: #selector(extractPDFAction), target: self)
-
- let shareMenuItem = NSMenuItem(title: KMLocalizedString("Share"), action: nil, target: self)
-
- shareMenuItem.submenu = NSSharingServicePicker.menu(forSharingItems: [showDocument?.documentURL ?? ""], subjectContext: "", withTarget: self, selector: NSSelectorFromString("sharePageItemAction:"), serviceDelegate: nil)
-
- let showFileSizeMenuItem = NSMenuItem(title: KMLocalizedString("Display Page Size"), action: #selector(displayPageSizeAction), target: self)
- showFileSizeMenuItem.state = isShowPageSize ? .on : .off
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
- if(selectedIndexPaths.count > 0) {
- menu.addItem(copyMenuItem)
- menu.addItem(cutMenuItem)
- if(copyPages.count > 0) {
- menu.addItem(pastMenuItem)
- }
- menu.addItem(deleteMenuItem)
- menu.addItem(NSMenuItem.separator())
- menu.addItem(rotateRightMenuItem)
- menu.addItem(rotateLeftMenuItem)
- menu.addItem(NSMenuItem.separator())
- if(selectedIndexPaths.count == 1) {
- menu.addItem(insertFileMenuItem)
- menu.addItem(insertBlankMenuItem)
- menu.addItem(replaceMenuItem)
- }
- menu.addItem(extractMenuItem)
- menu.addItem(shareMenuItem)
- menu.addItem(NSMenuItem.separator())
- menu.addItem(showFileSizeMenuItem)
- } else {
- if(copyPages.count > 0) {
- menu.addItem(pastMenuItem)
- menu.addItem(NSMenuItem.separator())
- } else {
- menu.addItem(pastNullMenuItem)
- menu.addItem(NSMenuItem.separator())
- }
- menu.addItem(showFileSizeMenuItem)
- }
- return menu
- }
-
- @objc public func insertFromPDFAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
- let selectedIndexPaths = collectionView.selectionIndexPaths
- let minimumIndexPath = selectedIndexPaths.min(by: { $0 < $1 })
- let open = NSOpenPanel()
- let insertPDF = KMNPDFInsertPDFWindowController(self.showDocument, currentPageIndex: minimumIndexPath?.item ?? 0)
- insertPDF.callback = { [weak self] fileAttribute, insertIdx in
- let doc = fileAttribute.pdfDocument
- self?.thumbnailBaseViewDelegate?.insertPDFThumbnailViewControlle?(pageEditVC: self, pdfDocment: doc)
- var insertIndex = insertIdx
-
- var insertPages: [CPDFPage] = []
- var indexpaths = Set<IndexPath>()
- for number in fileAttribute.fetchSelectPages() {
- if let page = doc?.page(at: UInt(number-1)) {
- insertPages.append(page)
- indexpaths.insert(IndexPath(item: insertIndex, section: 0))
- insertIndex += 1
- }
- }
-
- self?.insertFormPDF(insertPages: insertPages, pageDex: insertIdx)
- }
- insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
- }
-
- @objc public func insertFromBlankAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
- let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
- let insertPDF = KMNPDFInsertBlankWindowController(self.showDocument, currentPageIndex: maxmumIndexPath?.item ?? 0)
- insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
- }
-
- public func insertFromClipboardAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
- let selectedIndexPaths = collectionView.selectionIndexPaths
- let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
- let insertPDF = KMNPDFInsertClipboardWindowController(self.showDocument, currentPageIndex: maxmumIndexPath?.item ?? 0)
- insertPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
- }
-
- public func insertFromScannerAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
- let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
- let vc = KMDeviceBrowserWindowController.shared
- vc.type = .scanner
- vc.importScannerFileCallback = { [weak self] (url: NSURL) -> Void in
- if let imag = NSImage(contentsOfFile: url.path! ) {
- let index = (maxmumIndexPath?.item ?? 0) + 1
- let document = CPDFDocument()
- _ = document?.km_insertPage(imag.size, withImage: url.path! , at:UInt(index))
- self?.refreshDatas()
-
- }
- }
- vc.showWindow(nil)
- vc.window?.center()
- }
-
- public func canZoomInPageSize()->Bool {
- if pageThumbnailSize.width > defaultItemSize.width {
- return false
- }
- return true
- }
-
- public func canZoomOutPageSize()->Bool {
- if pageThumbnailSize.width < defaultItemSize.width {
- return false
- }
- return true
- }
-
- public func canUndo()->Bool {
- return true
- }
-
- public func undoPDFAction() {
-
- }
-
- public func redoPDFAction() {
-
- }
-
- public func canRodo()->Bool {
- return true
- }
-
- @objc public func extractPDFAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
- let selectedIndexPaths = collectionView.selectionIndexPaths
- if selectedIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
-
- let extractPDF = KMNExtractPDFWindowController(self.showDocument, selectionIndexPaths: collectionView.selectionIndexPaths)
- extractPDF.callback = { [weak self] oneDocumentPerPage, isDeletePage in
- extractPDF.own_closeEndSheet()
- if let _ = self?.showDocument {
- self?.extractPages(indexpaths: selectedIndexPaths, oneDocumentPerPage: oneDocumentPerPage, callback: { [weak self] result, params in
- if (result == .failure || result == .cancel) {
- return
- }
- if (isDeletePage) {
- self?.deletePages(indexpaths: selectedIndexPaths)
- }
- })
- }
- }
- extractPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
- }
-
- @objc public func replacePDFAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
-
- if selectedIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
-
- self.km_open_file_multi { [unowned self] index, params in
- if (self.fetchProgressBlockParamsIsPasswordFile(params: params)) { // 加密文档进度回调
- return
- }
-
- let tFileUrl = self.fetchProgressBlockParamsForFileUrl(params: params)
- let pdfExtensions = KMNConvertTool.supportPDFFileType()
- if let exn = tFileUrl?.pathExtension, pdfExtensions.contains(exn) {
- if (tFileUrl!.path.isPDFValid() == false) {
- let alert = NSAlert()
- alert.alertStyle = .critical
- alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
- alert.runModal()
- }
- }
- } completionBlock: { [unowned self] documents in
- self.replacePages(of: selectedIndexPaths, with: documents)
- }
- }
-
- public func splitPDFAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
-
- if collectionView.selectionIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.bounds.origin.x + self.view.bounds.size.width/2, self.view.bounds.size.height - 30))
- return
- }
-
- let splitPDF = KMNSplitPDFWindowController(self.showDocument,selectionIndexPaths: selectedIndexPaths)
- splitPDF.own_beginSheetModal(for: self.view.window, completionHandler: nil)
- }
-
- public func reversePDFAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
- let selectedIndexPaths = collectionView.selectionIndexPaths
-
- if selectedIndexPaths.count < 2 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("No page selected. Please select at least two pages to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
- reversePages(indexs: self.indexpathsToIndexs(indexpaths: selectedIndexPaths))
- }
-
- @objc public func rotatePageLeftAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- if collectionView.selectionIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
- rotatePages(indexPaths: collectionView.selectionIndexPaths, rotateAngle: -90)
- }
-
- @objc public func rotatePageRightAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- if collectionView.selectionIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
- rotatePages(indexPaths: collectionView.selectionIndexPaths, rotateAngle: 90)
- }
-
- public func deletePageAction() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- KMPurchaseCompareWindowController.sharedInstance()?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
- if selectedIndexPaths.count < 1 {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Please select one or more pages first to organize."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- } else if selectedIndexPaths.count == (showDocument?.pageCount ?? 0) {
- _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Can not delete all pages."), type: .info, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30))
- return
- }
-
- deletePages(indexpaths: selectedIndexPaths)
- }
-
- public func zoomInPageAction() { //放大
- if (canZoomInPageSize() == false) {
- return
- }
- let indexpaths = collectionView.selectionIndexPaths
- if (pageThumbnailSize.width < defaultItemSize.width) {
- pageThumbnailSize = defaultItemSize
- } else if (pageThumbnailSize.width == defaultItemSize.width) {
- pageThumbnailSize = NSSize(width: defaultItemSize.width*1.5, height: defaultItemSize.height*1.5)
- }
-
- collectionView.reloadData()
- collectionView.selectionIndexPaths = indexpaths
- }
-
- public func zoomOutPageAction() { //缩小
- if (canZoomOutPageSize() == false) {
- return
- }
- let indexpaths = collectionView.selectionIndexPaths
- if (pageThumbnailSize.width > defaultItemSize.width) {
- pageThumbnailSize = defaultItemSize
- } else if (pageThumbnailSize.width == defaultItemSize.width) {
- pageThumbnailSize = NSSize(width: defaultItemSize.width*0.5, height: defaultItemSize.height*0.5)
- }
-
- collectionView.reloadData()
- collectionView.selectionIndexPaths = indexpaths
- }
-
- @objc public func copyMenuItemAciton() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- let winC = KMPurchaseCompareWindowController.sharedInstance()
- winC?.showWindow(nil)
- return
- }
- KMNThumbnailManager.manager.copyPages = []
- let indexpaths = collectionView.selectionIndexPaths
- for indexpath in indexpaths.sorted() {
- guard let page = showDocument?.page(at: UInt(indexpath.item)).copy() as? CPDFPage else {
- continue
- }
-
- KMNThumbnailManager.manager.copyDocument.append(showDocument ?? CPDFDocument())
- KMNThumbnailManager.manager.copyPages.append(page)
- }
- }
-
- @objc public func pastMenuItemAciton() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- let winC = KMPurchaseCompareWindowController.sharedInstance()
- winC?.showWindow(nil)
- return
- }
-
- let selectedIndexPaths = collectionView.selectionIndexPaths
- var pastIndex = 1
- if(selectedIndexPaths.count > 0) {
- let maxmumIndexPath = selectedIndexPaths.max(by: { $0 < $1 })
- pastIndex = maxmumIndexPath?.item ?? 1
- }
-
- var indexpaths: Set<IndexPath> = []
- let copyPages = KMNThumbnailManager.manager.copyPages
- let page = copyPages.first
- if page?.document == showDocument {
- for (i, page) in copyPages.enumerated() {
- let zCopyPage = page.copy() as? CPDFPage
- if(zCopyPage != nil) {
- showDocument?.insertPageObject(zCopyPage, at: UInt(pastIndex+i))
- indexpaths.insert(IndexPath(item: pastIndex+i, section: 0))
- }
- }
- } else {
- if let pasteDocument = page?.document {
- var indexs: IndexSet = IndexSet()
- for (i, _) in copyPages.enumerated() {
- indexs.insert(i)
- indexpaths.insert(IndexPath(item: pastIndex+i, section: 0))
- }
- showDocument?.importPages(indexs, from: pasteDocument, at: UInt(pastIndex))
- }
- }
- refreshDatas()
- collectionView.reloadData()
- collectionView.selectionIndexPaths = indexpaths
- }
- @objc public func cutMenuItemAciton() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- let winC = KMPurchaseCompareWindowController.sharedInstance()
- winC?.showWindow(nil)
- return
- }
-
- let indexpaths = collectionView.selectionIndexPaths
- for indexpath in indexpaths.sorted() {
- guard let page = showDocument?.page(at: UInt(indexpath.item)).copy() as? CPDFPage else {
- continue
- }
-
- KMNThumbnailManager.manager.copyDocument.append(showDocument ?? CPDFDocument())
- KMNThumbnailManager.manager.copyPages.append(page)
-
- showDocument?.removePage(at: UInt(indexpath.item))
- refreshDatas()
- collectionView.reloadData()
- }
- }
-
- @objc public func deleteMenuItemAciton() {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- let winC = KMPurchaseCompareWindowController.sharedInstance()
- winC?.showWindow(nil)
- return
- }
- let indexpaths = collectionView.selectionIndexPaths
- for indexpath in indexpaths.sorted() {
-
- showDocument?.removePage(at: UInt(indexpath.item))
- refreshDatas()
- collectionView.reloadData()
- }
- }
-
- @objc func sharePageItemAction(menuItem:NSMenuItem) {
- if IAPProductsManager.default().isAvailableAllFunction() == false {
- let winC = KMPurchaseCompareWindowController.sharedInstance()
- winC?.showWindow(nil)
- return
- }
- let indexpaths = collectionView.selectionIndexPaths
- let doucument = self.showDocument
- let filename : String = doucument?.documentURL.lastPathComponent ?? ""
- let folderPath = (NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(filename)) ?? ""
-
- try? FileManager.default.removeItem(atPath: folderPath)
-
- let pdfdocument = CPDFDocument()
- let ret = pdfdocument?.importPages(indexpathsToIndexs(indexpaths: indexpaths), from: doucument, at: 0) ?? false
- let url = URL(fileURLWithPath: folderPath)
- if ret {
- let success = pdfdocument?.write(toFile: folderPath)
- let represent = menuItem.representedObject as? NSSharingService
- represent?.perform(withItems: [url])
- }
- }
- @objc public func displayPageSizeAction() {
- let indexpaths = collectionView.selectionIndexPaths
- isShowPageSize = !isShowPageSize
- collectionView.selectionIndexPaths = indexpaths
- }
- }
|