// // KMMainViewController+Action.swift // PDF Reader Pro // // Created by wanjun on 2022/12/15. // import Foundation extension KMMainViewController { func search(searchString: String, isCase: Bool, display: Bool = true, needShowAll: Bool = false) { let isEditing = self.listView?.isEditing() ?? false if isEditing { if searchString.isEmpty { self.listView.setHighlightedSelection(nil, animated: false) self.leftSideViewController.searchResults = [] if display { if self.leftSideViewController.findPaneState == .singular { self.leftSideViewController.displayFindViewAnimating(true) } else { self.leftSideViewController.displayGroupedFindViewAnimating(true) } } return } let isWholeWord = self.leftSideViewController.mwcFlags.wholeWordSearch == 1 // self.srHanddler.newSearch(keyword: searchString, isCase: isCase, isWholeWord: isWholeWord) { models in // KMPrint("") // } var opt = CPDFSearchOptions() if isCase == false { opt.insert(.caseSensitive) } if isWholeWord { opt.insert(.matchWholeWord) } let datas = self.srHanddler.pdfView?.document.findEditAllPageString(searchString, with: opt) ?? [] if let sel = datas.first?.first { self.srHanddler.showSelection(sel) } self.searchResults.removeAll() var _selections: [CPDFSelection] = [] for selections in datas { for selection in selections { let mode : KMSearchMode = KMSearchMode() mode.selection = selection mode.attributedString = KMOCToolClass.getAttributedString(selection: selection, keyword: searchString) mode.selectionPageIndex = self.listView.document.index(for: selection.page) self.searchResults.insert(mode, at: self.searchResults.count) _selections.append(selection) selection.setColor(NSColor(red: 236/255.0, green: 241/255.0, blue: 83/255.0, alpha: 0.5)) // self.listView.setHighlight(selection, forBorderColor: .yellow, fill: .red, animated: false) } // self.listView.setHighlightedSelections(selections ) } if needShowAll { self.listView.setHighlightedSelections(_selections) } if _selections.isEmpty { self.listView.setHighlightedSelection(nil, animated: false) } self.listView.setNeedsDisplayAnnotationViewForVisiblePages() self.leftSideViewController.searchResults = self.searchResults if display { if self.leftSideViewController.findPaneState == .singular { self.leftSideViewController.displayFindViewAnimating(true) } else { self.leftSideViewController.displayGroupedFindViewAnimating(true) } } return } let document = self.listView.document if let data = document?.isFinding, data { document?.cancelFindString() } if searchString == "" { self.searchResults = [] self.leftSideViewController.searchResults = self.searchResults self.listView.setHighlightedSelections([]) self.listView.setHighlightedSelection(nil, animated: false) self.listView.setNeedsDisplayAnnotationViewForVisiblePages() } else { mwcFlags.wholeWordSearch = isCase == true ? 1 : 0 var findArray : [[CPDFSelection]] if isCase { if self.leftSideViewController.mwcFlags.wholeWordSearch == 1 { findArray = self.listView.document.findString(searchString, with: .matchWholeWord) ?? [] } else { findArray = self.listView.document.findString(searchString) ?? [] } } else { if self.leftSideViewController.mwcFlags.wholeWordSearch == 1 { findArray = self.listView.document.findString(searchString, with: [.caseSensitive, .matchWholeWord]) ?? [] } else { findArray = self.listView.document.findString(searchString, with: .caseSensitive) ?? [] } } self.searchResults.removeAll() var _selections: [CPDFSelection] = [] for selections in findArray { for selection in selections { let mode : KMSearchMode = KMSearchMode() mode.selection = selection mode.attributedString = KMOCToolClass.getAttributedString(selection: selection, keyword: searchString) mode.selectionPageIndex = self.listView.document.index(for: selection.page) self.searchResults.insert(mode, at: self.searchResults.count) _selections.append(selection) selection.setColor(NSColor(red: 236/255.0, green: 241/255.0, blue: 83/255.0, alpha: 0.5)) // self.listView.setHighlight(selection, forBorderColor: .yellow, fill: .red, animated: false) } // self.listView.setHighlightedSelections(selections ) } if needShowAll { self.listView.setHighlightedSelections(_selections) } if _selections.isEmpty { self.listView.setHighlightedSelection(nil, animated: false) } self.listView.setNeedsDisplayAnnotationViewForVisiblePages() self.leftSideViewController.searchResults = self.searchResults } if display { if self.leftSideViewController.findPaneState == .singular { self.leftSideViewController.displayFindViewAnimating(true) } else { self.leftSideViewController.displayGroupedFindViewAnimating(true) } } } func removeSignatures(signatures:[CPDFSignature]) { for signature in signatures { self.listView.document.removeSignature(signature) } for i in 0.. 0 { mSignatures.append(sign) } } // self.leftSideViewController.signatureViewController.signatures = signatures // self.leftSideViewController.signatureViewController.reloadData() } //MARK: menu菜单 func fontColorMenuItem()->NSMenuItem { let fontColorItem = NSMenuItem(title: NSLocalizedString("Text Color", comment: ""), action: #selector(menuItemEditingClick_FontColor), keyEquivalent: "") return fontColorItem; } func fontSizeMenuItem()->NSMenuItem { let currentFontSize = self.listView.editingTextFontSize() let fontSizes = self.fontSizes() let submenu = NSMenu(title: "") for i in 0 ... fontSizes.count - 1 { let fontSize : String = fontSizes.object(at: i) as! String let item = NSMenuItem(title:fontSize , action: #selector(menuItemEditingClick_FontSize), keyEquivalent: "") item.target = self item.tag = i submenu.addItem(item) if (Int(currentFontSize) == Int(fontSize)) { item.state = .on } } let fontSizeItem = NSMenuItem(title: NSLocalizedString("Font Size", comment: ""), action:nil, keyEquivalent: "") fontSizeItem.submenu = submenu return fontSizeItem; } func corpImageMenuItem()->NSMenuItem { let corpImageItem = NSMenuItem(title: NSLocalizedString("Confirm crop", comment: ""), action: #selector(menuItemEditingClick_CropImage), target: self) return corpImageItem } func cancelCorpImageMenuItem()->NSMenuItem { let cancelCorpImageItem = NSMenuItem(title: NSLocalizedString("Cancel crop", comment: ""), action: #selector(menuItemEditingClick_CancelCrop), target: self) return cancelCorpImageItem } func restoreCorpImageMenuItem()->NSMenuItem { let cancelCorpImageItem = NSMenuItem(title: NSLocalizedString("Restore crop", comment: ""), action: #selector(menuItemEditingClick_RestoreCrop), target: self) return cancelCorpImageItem } func cutImageArea()->NSMenuItem { let deleteItem = NSMenuItem(title: NSLocalizedString("Crop", comment: ""), action: #selector(menuItemEditingClick_CutImage), target: self) return deleteItem } func editAddBlanMenu(menu:NSMenu){ _ = menu.insertItem(withTitle: NSLocalizedString("Add Text", comment: ""), action: #selector(addImageText), target: self, at: 0) _ = menu.insertItem(withTitle: NSLocalizedString("Add Image", comment: ""), action: #selector(addImageText), target: self, at: 1) } func addText() -> NSMenuItem { let addTextItem = NSMenuItem(title: NSLocalizedString("Add Text", comment: ""), action: #selector(addImageText), target: self, tag: 0) return addTextItem } func addImage() -> NSMenuItem { let addImageItem = NSMenuItem(title: NSLocalizedString("Add Image", comment: ""), action: #selector(addImageText), target: self, tag: 1) return addImageItem } func replaceImageArea()->NSMenuItem { let replaceItem = NSMenuItem(title: NSLocalizedString("Replace", comment: ""), action: #selector(menuItemEditingClick_ReplaceImage), target: self) return replaceItem } func exportImageArea()->NSMenuItem { let exportItem = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: #selector(menuItemEditingClick_ExportImage), target: self) let menu = NSMenu() let item1 = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportStampImage), target: self, tag:0, at: 0) let item2 = menu.insertItem(withTitle: NSLocalizedString("JPG", comment: ""), action:#selector(menuItemEditingClick_ExportImage), target: self, tag:1, at: 1) let item3 = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportStampImage), target: self, tag:2, at: 2) exportItem.submenu = menu return exportItem } func exportImageStampItem()->NSMenuItem { let exportItem = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: #selector(menuItemEditingClick_ExportImage), target: self) let menu = NSMenu() let item1 = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportStampImage), target: self, tag:0, at: 0) let item2 = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportStampImage), target: self, tag:2, at: 1) exportItem.submenu = menu return exportItem } func exportMenu() -> NSMenu { let menu = NSMenu() _ = menu.insertItem(withTitle: NSLocalizedString("PNG", comment: ""), action:#selector(exportCorpImage), target: self, tag:0, at: 0) _ = menu.insertItem(withTitle: NSLocalizedString("JPG", comment: ""), action:#selector(exportCorpImage), target: self, tag:1, at: 1) _ = menu.insertItem(withTitle: NSLocalizedString("PDF", comment: ""), action:#selector(exportCorpImage), target: self, tag:2, at: 2) return menu } func cropMenu() -> NSMenu { let menu = NSMenu() _ = menu.insertItem(withTitle: NSLocalizedString("Crop Current Page", comment: ""), action:#selector(cropCurrentPage), target: self, at: 0) _ = menu.insertItem(withTitle: NSLocalizedString("Crop All Pages", comment: ""), action:#selector(cropAllPage), target: self, at: 1) _ = menu.insertItem(withTitle: NSLocalizedString("Auto Crop – Separate", comment: ""), action:#selector(autoCropAll), target: self, at: 2) _ = menu.insertItem(withTitle: NSLocalizedString("Auto Crop – Combined", comment: ""), action:#selector(smartAutoCropAll), target: self, at: 2) return menu } func zoomSelectionMenuItem() -> NSMenuItem { let item = NSMenuItem(title: NSLocalizedString("Zoom To Selection", comment: ""), action: #selector(doZoomToAutoSelection), target: self) return item } func setDefaultAnnotationPorpert(type:CAnnotationType) -> NSMenuItem { let item = NSMenuItem(title: NSLocalizedString("Set as Default", comment: ""), action: #selector(defaultAnnotationPorpert), target: self, tag: type.rawValue) return item } func enterAnnotationStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Annotate", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() if listView.currentSelection != nil && listView.currentSelection.selectionType() == .text { _ = stypeMenu.addItem(withTitle: NSLocalizedString("Highlight", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 0) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Underline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 1) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Strikethrough", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Squiggly", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2) stypeMenu.addItem(NSMenuItem.separator()) } // stypeMenu.addItem(withTitle: NSLocalizedString("Freehand", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 0) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text Note", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 1) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Anchored Note", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 2) // stypeMenu.insertItem(NSMenuItem.separator(), at: 10000) stypeMenu.addItem(NSMenuItem.separator()) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Rectangle", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 3) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Circle", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 4) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Arrow", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 5) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Line", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 6) // stypeMenu.insertItem(NSMenuItem.separator(), at: 10000) if self.isReadMode { } else { stypeMenu.addItem(NSMenuItem.separator()) // _ = stypeMenu.addItem(withTitle: NSLocalizedString("Link", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 7) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Stamp", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 8) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Image", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 10) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Signature", comment: ""), action: #selector(menuItemAnnotationClick_addStype), target: self, tag: 9) } stypItem.submenu = stypeMenu if self.listView.annotationType == .ink { stypeMenu.item(withTitle: NSLocalizedString("Freehand", comment: ""))?.state = .on } else if self.listView.annotationType == .freeText { stypeMenu.item(withTitle: NSLocalizedString("Text Note", comment: ""))?.state = .on } else if self.listView.annotationType == .anchored { stypeMenu.item(withTitle: NSLocalizedString("Anchored Note", comment: ""))?.state = .on } else if self.listView.annotationType == .square { stypeMenu.item(withTitle: NSLocalizedString("Rectangle", comment: ""))?.state = .on } else if self.listView.annotationType == .circle { stypeMenu.item(withTitle: NSLocalizedString("Circle", comment: ""))?.state = .on } else if self.listView.annotationType == .arrow { stypeMenu.item(withTitle: NSLocalizedString("Arrow", comment: ""))?.state = .on } else if self.listView.annotationType == .line { stypeMenu.item(withTitle: NSLocalizedString("Line", comment: ""))?.state = .on } else if self.listView.annotationType == .link { stypeMenu.item(at: 7)?.state = .on } else if self.listView.annotationType == .stamp { stypeMenu.item(withTitle: NSLocalizedString("Stamp", comment: ""))?.state = .on } else if self.listView.annotationType == .signSignature { stypeMenu.item(withTitle: NSLocalizedString("Signature", comment: ""))?.state = .on } return stypItem } func setAnnotationToolStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Tool Mode", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.textToolMode.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Scroll", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.moveToolMode.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Magnify", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.magnifyToolMode.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Select", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: CToolMode.selectToolMode.rawValue) // stypeMenu.addItem(withTitle: NSLocalizedString("Zoom to Selected Area", comment: ""), action: #selector(menuItemAnnotationClick_toolModel), target: self, tag: 4) stypeMenu.insertItem(NSMenuItem.separator(), at: 4) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Highlight", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.highlight.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Underline", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.underline.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Strikethrough", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.strikeOut.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Squiggly", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.squiggly.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Freehand", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.ink.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Text Note", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.freeText.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Anchored Note", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.anchored.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Rectangle", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.square.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Circle", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.circle.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Arrow", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.arrow.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Line", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.line.rawValue) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Link", comment: ""), action: #selector(changeAnnotationMode_itemAction), target: self, tag: CAnnotationType.link.rawValue) stypItem.submenu = stypeMenu if self.toolbarController.toolbarType == .Annatiton { stypeMenu.item(at: 0)?.state = .on } else if self.toolbarController.toolbarType == .Move { stypeMenu.item(at: 1)?.state = .on } else if self.toolbarController.toolbarType == .Magnify { stypeMenu.item(at: 2)?.state = .on } else if self.toolbarController.toolbarType == .Select { stypeMenu.item(at: 3)?.state = .on } else if self.toolbarController.toolbarType == .SelectZoom { stypeMenu.item(at: 4)?.state = .on } return stypItem } func addReadModelStype() -> NSMenuItem { var stypItem = NSMenuItem(title: NSLocalizedString("Read Mode On", comment: ""), action: #selector(openReadModel), target: self) if self.isReadMode { stypItem = NSMenuItem(title: NSLocalizedString("Read Mode Off", comment: ""), action: #selector(closeReadModel), target: self) } return stypItem } func addOutlineStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Add Outline Item", comment: ""), action: #selector(addOutLineItemAction), target: self) return stypItem } func setTTSStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("TTS", comment: ""), action: #selector(showTTSView), target: self) return stypItem } func setShareStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Share", comment: ""), action: nil, target: self) var string = "" if listView.activeAnnotation != nil { string = self.listView?.activeAnnotation?.contents ?? "" } if string.count < 1{ string = self.listView?.currentSelection?.string() ?? "" } stypItem.submenu = NSSharingServicePicker.menu(forSharingItems: [string], subjectContext: "", withTarget: self, selector: #selector(shareFromService), serviceDelegate: nil) return stypItem } func numberOfChars(_ str: String) -> (num: Int, indexN: Int) { var number = 0 var indexN = 0 guard str.count > 0 else {return (0, 0)} for i in 0...str.count - 1 { let c: unichar = (str as NSString).character(at: i) if (c >= 0x4E00) { number += 2 }else { number += 1 } if number > 56{ indexN = i number = 100 break } } return (number, indexN) } func setLookUpStype() -> NSMenuItem { guard let str = listView?.currentSelection?.string() else { return NSMenuItem.separator() }//String(format: "Look Up %@", listView?.currentSelection?.string() ?? "") let dic = numberOfChars(str) var newStr = str if dic.num == 100{ newStr = str.prefix(dic.indexN) + "..." } newStr = NSLocalizedString("Look Up ", comment: "") + "\"" + newStr + "\"" let stypItem = NSMenuItem(title: newStr, action: #selector(lookUpAction), target: self) return stypItem } func setSearchBaiduStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Search with Baidu", comment: ""), action: #selector(searchBaiduAction), target: self) return stypItem } func setCutStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Cut", comment: ""), action: #selector(cutAction), target: self) return stypItem } func setDeleteStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Delete", comment: ""), action: #selector(deleteAction), target: self) return stypItem } func setColorsStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Colors", comment: ""), action: #selector(ColorsItemAction), target: self) return stypItem } func setLinesStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Lines", comment: ""), action: #selector(LinesItemAction), target: self) return stypItem } func setEditNoteStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Edit Note", comment: ""), action: #selector(EditNoteItemAction), target: self) return stypItem } func setRotateStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Rotate", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Rotate Left", comment: ""), action: #selector(rotateLeftAction), target: self, tag: 0) let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Rotate Right", comment: ""), action: #selector(rotateRightAction), target: self, tag: 1) stypItem.submenu = stypeMenu if self.toolbarController.toolbarType == .Annatiton { stypeMenu.item(at: 0)?.state = .on } else if self.toolbarController.toolbarType == .Move { stypeMenu.item(at: 1)?.state = .on } return stypItem } func setNextPageStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Next Page", comment: ""), action: #selector(NextPageAction), target: self) stypItem.isEnabled = false if listView.canGoToNextPage() { stypItem.isEnabled = true } return stypItem } func setPreviousPageStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Previous Page", comment: ""), action: #selector(PreviousPageAction), target: self) stypItem.isEnabled = false if listView.canGoToPreviousPage() { stypItem.isEnabled = true } return stypItem } func setTranslateStype() -> NSMenuItem { let str = listView?.currentSelection?.string() ?? ""//String(format: "Translate %@", listView?.currentSelection?.string() ?? "") let dic = numberOfChars(str) var newStr = str if dic.num == 100{ newStr = str.prefix(dic.indexN) + "..." } newStr = NSLocalizedString("Translate", comment: "") + " \"" + newStr + "\"" let stypItem = NSMenuItem(title: newStr, action: #selector(TranslateItemAction), target: self) return stypItem } func setAutoScrollStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Auto Scroll", comment: ""), action: #selector(AutoScrollItemAction), target: self) stypItem.state = self.listView.isAutoFlow() ? .on : .off return stypItem } func setSnapshotStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Snapshot", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Auto", comment: ""), action: #selector(takeSnapshot), target: self, tag: 0) let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Select Area", comment: ""), action: #selector(takeSnapshotSelectContent), target: self, tag: 1) stypItem.submenu = stypeMenu // if self.toolbarController.toolbarType == .Annatiton { // stypeMenu.item(at: 0)?.state = .on // } else if self.toolbarController.toolbarType == .Move { // stypeMenu.item(at: 1)?.state = .on // } return stypItem } func setServicesStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Services", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() let item1 = stypeMenu.addItem(withTitle: NSLocalizedString("Add to Music as a Spoken Track", comment: ""), action: #selector(AddtoMusicasASpokenTrack), target: self, tag: 0) let item2 = stypeMenu.addItem(withTitle: NSLocalizedString("Convert Text to Simplified Chinese", comment: ""), action: #selector(ConvertTextToSimplifiedChinese), target: self, tag: 1) let item3 = stypeMenu.addItem(withTitle: NSLocalizedString("Convert Text to Traditional Chinese", comment: ""), action: #selector(ConvertTextToTraditionalChinese), target: self, tag: 2) let item4 = stypeMenu.addItem(withTitle: NSLocalizedString("Open", comment: ""), action: #selector(OpenItemAction), target: self, tag: 3) let item5 = stypeMenu.addItem(withTitle: NSLocalizedString("Search With Baidu", comment: ""), action: #selector(searchBaiduAction), target: self, tag: 4) let item6 = stypeMenu.addItem(withTitle: NSLocalizedString("Show in Finder", comment: ""), action: #selector(showInFinder), target: self, tag: 4) let item7 = stypeMenu.addItem(withTitle: NSLocalizedString("Show Info in Finder", comment: ""), action: #selector(showInfoInFinder), target: self, tag: 5) stypItem.submenu = stypeMenu // if self.toolbarController.toolbarType == .Annatiton { // stypeMenu.item(at: 0)?.state = .on // } else if self.toolbarController.toolbarType == .Move { // stypeMenu.item(at: 1)?.state = .on // } return stypItem } func setCropStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("Crop", comment: ""), action: nil, target: self) let stypeMenu = NSMenu() _ = stypeMenu.addItem(withTitle: NSLocalizedString("Crop All Pages", comment: ""), action: #selector(cropAllPageItem), target: self, tag: 0) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Crop Current Page", comment: ""), action: #selector(cropCurrentPageItem), target: self, tag: 1) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Auto Crop – Separate", comment: ""), action: #selector(autoCropAllItem), target: self, tag: 2) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Auto Crop – Combined", comment: ""), action: #selector(smartAutoCropAllItem), target: self, tag: 3) if NSIsEmptyRect(listView.selectionRect){ _ = stypeMenu.addItem(withTitle: NSLocalizedString("Select Area", comment: ""), action: #selector(selectToolModel), target: self, tag: 4) _ = stypeMenu.addItem(withTitle: NSLocalizedString("Crop Options...", comment: ""), action: #selector(customCropModel), target: self, tag: 5) } stypItem.submenu = stypeMenu // if self.toolbarController.toolbarType == .Annatiton { // stypeMenu.item(at: 0)?.state = .on // } else if self.toolbarController.toolbarType == .Move { // stypeMenu.item(at: 1)?.state = .on // } else if self.toolbarController.toolbarType == .Magnify { // stypeMenu.item(at: 2)?.state = .on // } else if self.toolbarController.toolbarType == .Select { // stypeMenu.item(at: 3)?.state = .on // } else if self.toolbarController.toolbarType == .SelectZoom { // stypeMenu.item(at: 4)?.state = .on // } return stypItem } func setAITranslateStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("AI Translate", comment: ""), action: #selector(AITranslateItemAction), target: self) stypItem.state = self.listView.isAutoFlow() ? .on : .off return stypItem } func setAIProofreadStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("AI Proofread", comment: ""), action: #selector(AIProofreadItemAction), target: self) stypItem.state = self.listView.isAutoFlow() ? .on : .off return stypItem } func setAIRewriteStype() -> NSMenuItem { let stypItem = NSMenuItem(title: NSLocalizedString("AI Rewrite", comment: ""), action: #selector(AIRewriteItemAction), target: self) stypItem.state = self.listView.isAutoFlow() ? .on : .off return stypItem } func addHighlightLinksStype() -> NSMenuItem { let highlightLink = KMPreferenceManager.shared.highlightLinks var highlightLinkTitle = NSLocalizedString("Highlight Links", comment: "") if highlightLink { highlightLinkTitle = NSLocalizedString("Disable Highlight Links", comment: "") } let highlightLinksItem = NSMenuItem(title: highlightLinkTitle, action: #selector(highlightLinks), target: self) return highlightLinksItem } func addAnnotationForStyleMenu(_ item: NSMenuItem?) { if item == nil { return } let menu = NSMenu() item?.submenu = menu let height = NSMenuItem(title: NSLocalizedString("Highlight", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 0) let underline = NSMenuItem(title: NSLocalizedString("Underline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 1) let strickout = NSMenuItem(title: NSLocalizedString("Strikethrough", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2) let wavyLine = NSMenuItem(title: NSLocalizedString("Squiggly", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 2) let text = NSMenuItem(title: NSLocalizedString("Text", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 3) let note = NSMenuItem(title: NSLocalizedString("Note", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 4) let rectangle = NSMenuItem(title: NSLocalizedString("Rectangle", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 5) let oval = NSMenuItem(title: NSLocalizedString("Oval", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 6) let line = NSMenuItem(title: NSLocalizedString("Line", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 7) let link = NSMenuItem(title: NSLocalizedString("Add Link", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 8) let outline = NSMenuItem(title: NSLocalizedString("Add Outline", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 9) let aiTranslation = NSMenuItem(title: NSLocalizedString("AI Translation", comment: ""), action: #selector(aiTranslationAction), target: self) // let tts = NSMenuItem(title: NSLocalizedString("TTS", comment: ""), action: #selector(menuItemAnnotationClick_add), target: self, tag: 10)! menu.insertItem(NSMenuItem.separator(), at: menu.items.count) if listView.currentSelection.selectionType() != .image { menu.insertItem(height, at: menu.items.count) menu.insertItem(underline, at: menu.items.count) menu.insertItem(strickout, at: menu.items.count) menu.insertItem(wavyLine, at: menu.items.count) menu.insertItem(NSMenuItem.separator(), at: menu.items.count) } if self.isReadMode { } else { if listView.currentSelection.selectionType() != .image && listView.currentSelection.selectionType() != .text { menu.insertItem(text, at: menu.items.count) menu.insertItem(note, at: menu.items.count) } } if self.isReadMode { } else { if listView.currentSelection.selectionType() != .image { menu.insertItem(NSMenuItem.separator(), at: menu.items.count) menu.insertItem(rectangle, at: menu.items.count) menu.insertItem(oval, at: menu.items.count) } } if self.isReadMode { } else { if listView.currentSelection.selectionType() != .image && listView.currentSelection.selectionType() != .text { menu.insertItem(line, at: menu.items.count) } } menu.insertItem(NSMenuItem.separator(), at: menu.items.count) if self.isReadMode { } else { menu.insertItem(link, at: menu.items.count) } if self.isReadMode { } else { if listView.currentSelection.selectionType() != .image { menu.insertItem(outline, at: menu.items.count) } } menu.insertItem(NSMenuItem.separator(), at: menu.items.count) if self.isReadMode { } else { if (listView.currentSelection.selectionType() != .image) { menu.insertItem(aiTranslation, at: menu.items.count) } } menu.insertItem(NSMenuItem.separator(), at: menu.items.count) } func addBookmarkMenu() -> NSMenuItem { if self.listView.document.bookmark(forPageIndex: UInt(self.listView.currentPageIndex)) == nil { let bookMarkItem = NSMenuItem(title: NSLocalizedString("Add Bookmark", comment: ""), action: #selector(menuItemBookMarkClick_add), target: self) return bookMarkItem } else { let bookMarkItem = NSMenuItem(title: NSLocalizedString("Remove Bookmark", comment: ""), action: #selector(menuItemBookMarkClick_add), target: self) return bookMarkItem } } func findStringMenu() -> NSMenuItem { let menuItem = NSMenuItem(title: NSLocalizedString("Find", comment: ""), action: #selector(menuItemAnnotationClick_FindString), target: self) menuItem.keyEquivalent = "f" return menuItem } func printingMenu() -> NSMenuItem { let menuItem = NSMenuItem(title: NSLocalizedString("Print", comment: ""), action: #selector(menuItemAnnotationClick_Print), keyEquivalent: "p") return menuItem } func fontSizes()->NSArray { return ["6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "24", "36", "48", "72", "96", "144", "288"] } func handleRightMouseDown(theEvent: NSEvent) -> Bool { if interactionMode == .presentation { listView.goToPreviousPage(nil) return true } return false } func canEnterFullscreen() -> Bool { if (mwcFlags.isSwitchingFullScreen != 0) { return false } if useNativeFullScreen() { return interactionMode == .normal || interactionMode == .presentation } else { return !self.listView.document.isLocked && (interactionMode == .normal || interactionMode == .presentation) && self.view.window?.tabbedWindows?.count ?? 0 < 2 } } override func canEnterPresentation() -> Bool { let can = super.canEnterPresentation() if can == false { return false } guard let doc = self.listView?.document, doc.isLocked == false else { return false } return can } func useNativeFullScreen() -> Bool { var isFull = false // NSWindow.instancesRespond(toSelector: #selector(toggleFullScreen:)) let sel = NSSelectorFromString("toggleFullscreen:") if NSWindow.instancesRespond(to: sel) && UserDefaults.standard.bool(forKey: "SKUseLegacyFullScreenKey"){ isFull = true } return isFull } func enterPresentation() { self.view.window?.enterPresentation(provider: self) } func removeBlankingWindows() { // blankingWindows.makeObjectsPerform(#selector(fadeOut)) // blankingWindows = nil } func hideLeftSideWindow() { // if leftSideViewController.view.window == leftSideWindow { // self.leftView.remove() // if leftSideWindow.firstResponder()?.isDescendant(of: leftSideController.view()) { // leftSideWindow.makeFirstResponder(nil) // } // leftSideController.view().setFrame(SKShrinkRect(NSInsetRect(leftSideContentView.bounds, -1.0, -1.0), 1.0, .maxYEdge)) // leftSideContentView.addSubview(leftSideController.view()) // // if self.interactionMode() == SKPresentationMode { // self.setLeftSidePaneState(mwcFlags.savedLeftSidePaneState) // } // // leftSideWindow = nil // } } func hideRightSideWindow() { // if rightSideController.view().window() == rightSideWindow { // rightSideWindow.remove() // if rightSideWindow.firstResponder()?.isDescendant(of: rightSideController.view()) { // rightSideWindow.makeFirstResponder(nil) // } // rightSideController.view().setFrame(SKShrinkRect(NSInsetRect(rightSideContentView.bounds, -1.0, -1.0), 1.0, .maxYEdge)) // rightSideContentView.addSubview(rightSideController.view()) // // rightSideWindow = nil // } } func forceSubwindowsOnTop(_ flag: Bool) { // let winC: NSWindowController = self.kmCurrentWindowC! // for wc in winC.document!.windowControllers { // let sel = NSSelectorFromString("setForceOnTop:") // if wc.responds(to: sel){ // wc. // } // } } func enterPresentationMode() { let scrollView = listView.documentView().enclosingScrollView savedNormalSetup.setValue(scrollView?.hasHorizontalScroller, forKey: KMMainModel.Key.kHasHorizontalScroller) savedNormalSetup.setValue(scrollView?.hasVerticalScroller, forKey: KMMainModel.Key.kHasVerticalsCroller) savedNormalSetup.setValue(scrollView?.autohidesScrollers, forKey: KMMainModel.Key.kAutoHidesScrollers) // Set up presentation mode // if RUNNING(version: 10_12) { // pdfView.setBackgroundColor(NSColor.black) // } else { listView.backgroundColor = NSColor.clear // } listView.setDisplay(.singlePage) listView.autoScales = true listView.displayBox = .cropBox listView.displaysPageBreaks = false scrollView?.autohidesScrollers = true scrollView?.hasHorizontalScroller = false scrollView?.hasVerticalScroller = false listView.setCurrentSelection(nil, animate: true) // if listView.hasReadingBar() { // listView.toggleReadingBar() // } // myDocument!.currentPage(presentationNotesDocument.pdfDocument().page(at: listView.currentPage().pageIndex())) // Prevent sleep // if activityAssertionID == kIOPMNullAssertionID && kIOReturnSuccess != IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, "Skim" as CFString, &activityAssertionID) { // activityAssertionID = kIOPMNullAssertionID // } } func exitFullscreenMode() { if self.interactionMode == .presentation { self.exitPresentationMode() } self.applyPDFSettings(self.savedNormalSetup) self.savedNormalSetup.removeAllObjects() self.listView.layoutDocumentView() self.listView.requiresDisplay() // if ([[[self pdfView] currentPage] isEqual:page] == NO) // [[self pdfView] goToPage:page]; if let backgroundColor = UserDefaults.standard.color(forKey: KMBackgroundColorKey) { self.listView.backgroundColor = backgroundColor self.secondaryPdfView?.backgroundColor = backgroundColor } } func applyPDFSettings(_ setup: NSDictionary) { if let data = setup.object(forKey: KMMainModel.Key.kAutoScales) as? NSNumber { self.listView.autoScales = data.boolValue } if self.listView.autoScales == false { if let data = setup.object(forKey: KMMainModel.Key.kScaleFactor) as? NSNumber { self.listView.scaleFactor = data.floatValue.cgFloat } } if let data = setup.object(forKey: KMMainModel.Key.kDisplayMode) as? NSNumber { self.listView.setDisplay(CPDFDisplayViewMode(rawValue: data.intValue) ?? .singlePage) } if let data = setup.object(forKey: KMMainModel.Key.kDisplaysAsBook) as? NSNumber { self.listView.displaysAsBook = data.boolValue } if let data = setup.object(forKey: KMMainModel.Key.kDisplaysPageBreaks) as? NSNumber { self.listView.displaysPageBreaks = data.boolValue } if let data = setup.object(forKey: KMMainModel.Key.kDisplayBox) as? NSNumber { // self.listView.displayBox = CPDFDisplayBox(rawValue: data.intValue) ?? .cropBox } self.listView.layoutDocumentView() // self.savePageNumberIfNeed() } func exitPresentationMode() { // if (activityAssertionID != kIOPMNullAssertionID && kIOReturnSuccess == IOPMAssertionRelease(activityAssertionID)) // activityAssertionID = kIOPMNullAssertionID; // // NSScrollView *scrollView = [[pdfView documentView] enclosingScrollView]; // [scrollView setHasHorizontalScroller:[[savedNormalSetup objectForKey:HASHORIZONTALSCROLLER_KEY] boolValue]]; // [scrollView setHasVerticalScroller:[[savedNormalSetup objectForKey:HASVERTICALSCROLLER_KEY] boolValue]]; // [scrollView setAutohidesScrollers:[[savedNormalSetup objectForKey:AUTOHIDESSCROLLERS_KEY] boolValue]]; self.selectDisplay(display: KMPDFDisplayType(rawValue: KMPDFDisplayType.RawValue(self.listView.fetchDisplayViewMode().rawValue)) ?? .singlePage, viewSettingIsReload: false) // NotificationCenter.default.post(name: NSNotification.Name(rawValue: "CPDFListViewDisplayModeChangeNotification"), object: nil) } func currentPDFSettings() -> NSDictionary { let setup = NSMutableDictionary() setup[KMMainModel.Key.kDisplaysPageBreaks] = NSNumber(value: listView.displaysPageBreaks) setup[KMMainModel.Key.kDisplaysAsBook] = NSNumber(value: listView.displaysAsBook) setup[KMMainModel.Key.kDisplayBox] = NSNumber(value: listView.displayBox.rawValue) setup[KMMainModel.Key.kScaleFactor] = NSNumber(value: listView.scaleFactor) setup[KMMainModel.Key.kAutoScales] = NSNumber(value: listView.autoScales) setup[KMMainModel.Key.kDisplayMode] = NSNumber(value: listView.fetchDisplayViewMode().rawValue) return setup } //MARK: menuItem Action @objc func menuItemEditingClick_FontColor(sender: NSMenuItem) { let color = listView.editingSelectionFontColor() let panel = NSColorPanel.shared panel.setTarget(self) panel.setAction(#selector(fontColorChangeAction)) panel.orderFront(nil) panel.showsAlpha = false panel.color = color ?? NSColor.black } @objc func fontColorChangeAction(sender: NSColorPanel) { self.listView.setEditingSelectionFontColor(sender.color) } @objc func menuItemEditingClick_FontSize(sender: NSMenuItem) { let fontSize = self.fontSizes().object(at: sender.tag) self.listView.setEditingSelectionFontSize(CGFloat(Int(fontSize as! String)!)) } @objc func addImageText(sender: NSMenuItem) { let event = NSApp.currentEvent let clickLocation = event?.locationInWindow var point = self.listView.convert(clickLocation!, from: NSApp.mainWindow?.contentView) var point2 = self.listView.convert(point, to: self.listView.currentPage()) point2 = CGPoint(x: self.listView.bounds.width - point2.x, y: self.listView.bounds.height - point2.y) point = point2 if sender.tag == 0 { KMPrint("添加文字") let isSelect = self.toolbarController.findItem(KMToolbarAddTextEditPDFItemIdentifier)?.isSelected ?? false if !isSelect { self.toolbarController.selectItem(KMToolbarAddTextEditPDFItemIdentifier) } // self.pdfViewEditingAddTextArea(self.listView, add: CGRectMake(point.x, point.y, 0, 0)) } else if sender.tag == 1 { KMPrint("添加图片") let isSelect = self.toolbarController.findItem(KMToolbarAddImageEditPDFItemIdentifier)?.isSelected ?? false if !isSelect { self.toolbarController.selectItem(KMToolbarAddImageEditPDFItemIdentifier) } // self.pdfViewEditingAddImageArea(self.listView, add: CGRectMake(point.x, point.y, 0, 0)) } else if sender.tag == 2 { KMPrint("粘贴") } } @objc func menuItemEditingClick_CropImage(sender: NSMenuItem) { if self.rightSideViewController.eidtPDFImageProperty != nil { self.rightSideViewController.eidtPDFImageProperty.confirmVCImageAction((Any).self) } else { if self.listView.cropAreas != nil && self.listView.selectImageAreas != nil{ self.listView.cropEditImageArea(self.listView.selectImageAreas, withBounds: self.listView.cropAreas.cropRect) } } } @objc func menuItemEditingClick_CancelCrop(sender: NSMenuItem) { if self.rightSideViewController.eidtPDFImageProperty != nil { self.rightSideViewController.eidtPDFImageProperty?.cancelCutImageAction("") } else { self.listView.exitCrop(with: self.listView.selectImageAreas) self.listView.cropAreas = nil self.listView.isEditImage = false } } @objc func menuItemEditingClick_RestoreCrop(sender: NSMenuItem) { if self.rightSideViewController.eidtPDFImageProperty != nil { self.rightSideViewController.eidtPDFImageProperty?.restoreCutImageAction("") } else { self.listView.resetCrop(with: self.listView.selectImageAreas) } } @objc func menuItemEditingClick_CutImage(sender: NSMenuItem) { // if self.listView.selectImageAreas != nil { // self.listView.isEditImage = true // self.listView.enterCrop(with: self.listView.selectImageAreas) // self.rightSideViewController.eidtPDFImageProperty.updateButtonState(hidden: false) // } self.editPDFHanddler.cropAction() } @objc func menuItemEditingClick_ReplaceImage(sender: NSMenuItem) { if self.listView.selectImageAreas == nil { return } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Replace"]) let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.allowedFileTypes = ["png","jpg"] panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { let openPath = panel.url?.path let s = self.listView.replace(self.listView.selectImageAreas, imagePath: openPath!) if s { } } } } @objc func menuItemEditingClick_ExportImage(sender: NSMenuItem) { if self.listView.selectImageAreas == nil { return } let panel = NSSavePanel() // panel.nameFieldStringValue = "[新文件].png" panel.nameFieldStringValue = "\(NSLocalizedString("Untitled", comment: "")).jpg" // let button = NSButton.init(checkboxWithTitle: "保存后打开文档", target: nil, action: nil) // button.state = .on // panel.accessoryView = button panel.isExtensionHidden = true let response = panel.runModal() if response == .OK { let url = panel.url if FileManager.default.fileExists(atPath: url!.path) { try?FileManager.default.removeItem(atPath: url!.path) } let result = self.listView.extractImage(with: self.listView.selectImageAreas, toImagePath: url!.path) if result { NSWorkspace.shared.activateFileViewerSelecting([url!]) // if button.state == .on { /// 开启文档 // NSWorkspace.shared.openFile(url!.path) // } else { // // } } } } @objc func AddtoMusicasASpokenTrack(sender: NSMenuItem) { } @objc func ConvertTextToSimplifiedChinese(sender: NSMenuItem) { } @objc func ConvertTextToTraditionalChinese(sender: NSMenuItem) { } @objc func OpenItemAction(sender: NSMenuItem) { } @objc func cropAllPageItem(sender: NSMenuItem) { self.cropAll(nil) } @objc func cropCurrentPageItem(sender: NSMenuItem) { self.crop(nil) } @objc func autoCropAllItem(sender: NSMenuItem) { self.autoCropAll(nil) } @objc func smartAutoCropAllItem(sender: NSMenuItem) { self.smartAutoCropAll(nil) } @objc func customCropModel(sender: NSMenuItem) { let pdfDoc: CPDFDocument = self.listView.document if !pdfDoc.allowsCopying || !pdfDoc.allowsPrinting { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } let window = NSWindow.currentWindow() let currentPage = pdfDoc.index(for: self.listView.currentPage()) let cropVC = KMPDFCropWindowController(document: pdfDoc, pwd: "", currentPage: Int(currentPage), cropSize: NSMakeRect(100, 100, 50, 80), selectPageString: "\(currentPage)") window.km_beginSheet(windowC: cropVC) cropVC.cropWindowCloseBlock = { [weak self] doc in window.km_quick_endSheet() let isSuccessful = doc.write(to: self?.listView.document?.documentURL) if isSuccessful { if let documen = CPDFDocument(url: self?.document?.documentURL) { if documen.isLocked { documen.unlock(withPassword: pdfDoc.password) } self?.setDocument = documen } } } } @objc func rotateRightAction(sender: NSMenuItem) { } @objc func rotateLeftAction(sender: NSMenuItem) { } @objc func menuItemAnnotationClick_toolModel(sender: NSMenuItem) { self.listView.toolMode = .noteToolMode var identifier = KMDocumentAnnotationToolbarItemIdentifier var model : KMToolbarViewType = .None switch sender.tag { case 0: identifier = KMDocumentAnnotationToolbarItemIdentifier model = .Annatiton case 1: identifier = KMToolbarMoveToolModeItemIdentifier model = .Move case 2: identifier = KMToolbarMagnifyToolModeItemIdentifier model = .Magnify case 3: identifier = KMToolbarSelectToolModeItemIdentifier model = .Select case 4: identifier = KMToolbarZoomToSelectionItemIdentifier model = .SelectZoom default: break } let item : KMToolbarItemView = (self.toolbarController.mainToolBarView?.toolbarItemFindItemIdentifiers(value: identifier))! self.toolbarController.mainToolBarView?.delegate?.toolbarViewController?(self.toolbarController.mainToolBarView!, clickMode:model, toolbar: item, []) } @objc func changeAnnotationMode_itemAction(sender : NSMenuItem) { var itemId: String? if sender.tag == CAnnotationType.highlight.rawValue { itemId = KMToolbarHighlightAnnotationItemIdentifier } else if sender.tag == CAnnotationType.underline.rawValue { itemId = KMToolbarUnderlineAnnotationItemIdentifier } else if sender.tag == CAnnotationType.strikeOut.rawValue { itemId = KMToolbarStrikeOutAnnotationItemIdentifier } else if sender.tag == CAnnotationType.squiggly.rawValue { itemId = KMToolbarSquigglyAnnotationItemIdentifier } else if sender.tag == CAnnotationType.ink.rawValue { itemId = KMToolbarInkAnnotationItemIdentifier } else if sender.tag == CAnnotationType.freeText.rawValue { itemId = KMToolbarFreeTextAnnotationItemIdentifier } else if sender.tag == CAnnotationType.anchored.rawValue { itemId = KMToolbarAnchoredAnnotationItemIdentifier } else if sender.tag == CAnnotationType.square.rawValue { itemId = KMToolbarSquareAnnotationItemIdentifier } else if sender.tag == CAnnotationType.circle.rawValue { itemId = KMToolbarCircleAnnotationItemIdentifier } else if sender.tag == CAnnotationType.arrow.rawValue { itemId = KMToolbarArrowAnnotationItemIdentifier } else if sender.tag == CAnnotationType.line.rawValue { itemId = KMToolbarLineAnnotationItemIdentifier } else if sender.tag == CAnnotationType.link.rawValue { itemId = KMToolbarLinkAnnotationItemIdentifier } if let data = itemId { self.toolbarController.clickItem(data) } } @objc func menuItemAnnotationClick_add(sender : NSMenuItem) { var annotationType : CAnnotationType = .unkown switch sender.tag { case 0: annotationType = .highlight case 1: annotationType = .underline case 2: if sender.title == NSLocalizedString("Squiggly", comment: "") { annotationType = .squiggly } else { annotationType = .strikeOut } case 3: annotationType = .freeText case 4: annotationType = .anchored case 5: annotationType = .square case 6: annotationType = .circle case 7: annotationType = .line case 8: annotationType = .link case 9: // var newOutline : CPDFOutline = CPDFOutline() // newOutline.label = "11111111" // let des = self.listView.currentDestination // if "\(des?.point.x ?? 0)" != "nan" { // newOutline.destination = self.listView.currentDestination // } else { // let destination : CPDFDestination = CPDFDestination(document: self.listView.document, pageIndex: self.listView.currentPageIndex, at: CGPoint(x: 0, y: 0), zoom: self.listView.scaleFactor) // newOutline.destination = destination // } // let current = self.listView.document.outlineRoot().insertChild(at: 0) ?? CPDFOutline() // let parent = current.parent ?? CPDFOutline() // let index = current.index + 1 // parent.insertChild(newOutline, at: index) if self.model.leftPanelOpen == false || self.leftSideViewController.type.methodType != .Outline { self.leftSideViewController.refreshMethodType(methodType: .Outline) } // self.leftSideViewController.outlineViewController.addItemAction() return case 10: annotationType = .unkown default: break } if (annotationType != .link) { self.listView.addAnnotation(with: annotationType, selection: self.listView.currentSelection, page: self.listView.currentSelection.page, bounds: self.listView.currentSelection.bounds) self.listView.currentSelection = nil; return } // link let selection = self.listView.currentSelection self.toolbarController.selectItem(KMToolbarLinkAnnotationItemIdentifier) DispatchQueue.main.async { Task { @MainActor in let annotation = self.listView.addAnnotation(with: annotationType, selection: selection, page: selection?.page, bounds: selection!.bounds) self.listView.currentSelection = nil; if (annotation != nil) { self.listView.updateActiveAnnotations([annotation!]) } } } } @objc func aiTranslationAction(sender: NSMenuItem) { let content = self.listView.currentSelection.string() ?? "" let origin = self.listView.currentSelection.bounds.origin self.aiTranslationWindow = KMAITranslationWindowController.init(windowNibName: "KMAITranslationWindowController") self.aiTranslationWindow?.content = content self.view.window!.addChildWindow(self.aiTranslationWindow!.window!, ordered: NSWindow.OrderingMode.above) self.aiTranslationWindow!.window?.center() } @objc func menuItemAnnotationClick_addStype(sender: NSMenuItem) { Task { @MainActor in let idx = sender.tag if idx == 10 { if KMMemberInfo.shared.isMemberAllFunction == false { KMMemberInfo.shared.advancedFunctionUsage() return } } var point = mouseRightMenuEvent?.locationInWindow if (point == nil) { point = NSZeroPoint } let currentPoint: NSPoint = self.listView.convert(point!, from: self.listView.superview) let currentPage = self.listView.page(for: currentPoint, nearest: true) var pagePoint = self.listView.convert(currentPoint, to: currentPage) var annotation: CPDFAnnotation? if self.isReadMode { if (sender.tag == 0 || sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign self.listView.toolMode = .noteToolMode } switch sender.tag { case 0: self.listView.annotationType = CAnnotationType.ink case 1: // self.listView.annotationType = CAnnotationType.freeText let defaultSize = self.listView.defaultSize(with: .freeText, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .freeText, selection: nil, page: currentPage, bounds: bounds) if ((annotation) != nil) { self.listView.updateActiveAnnotations([annotation!]) self.listView.edit(annotation) } case 2: // self.listView.annotationType = CAnnotationType.anchored let defaultSize = self.listView.defaultSize(with: .anchored, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .anchored, selection: nil, page: currentPage, bounds: bounds) self.listView.edit(annotation) case 3: // self.listView.annotationType = CAnnotationType.square let defaultSize = self.listView.defaultSize(with: .square, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .square, selection: nil, page: currentPage, bounds: bounds) case 4: // self.listView.annotationType = CAnnotationType.circle let defaultSize = self.listView.defaultSize(with: .circle, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .circle, selection: nil, page: currentPage, bounds: bounds) case 5: // self.listView.annotationType = CAnnotationType.arrow let defaultSize = self.listView.defaultSize(with: .arrow, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .arrow, selection: nil, page: currentPage, bounds: bounds) case 6: // self.listView.annotationType = CAnnotationType.line let defaultSize = self.listView.defaultSize(with: .line, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .line, selection: nil, page: currentPage, bounds: bounds) case 7: self.listView.annotationType = CAnnotationType.link self.openRightPane() case 8: self.listView.annotationType = CAnnotationType.stamp self.openRightPane() case 9: self.listView.annotationType = CAnnotationType.signSignature self.openRightPane() default: break } self.rightSideViewController.isHidden = true self.rightSideViewController.subViewType = .AnnotationProperts } else { if (sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign if(self.toolbarController.toolbarType == .None) { self.toolbarController.toolbarType = .Annatiton } self.listView.toolMode = .noteToolMode } switch sender.tag { case 0: self.toolbarController.ignoreCurrentAnnotationTypeChange = true self.model.rightMouseEventing = true if(self.toolbarController.toolbarType == .None) { self.toolbarController.toolbarType = .Annatiton } self.listView.toolMode = .noteToolMode self.listView.annotationType = CAnnotationType.ink case 1: // self.listView.annotationType = CAnnotationType.freeText let defaultSize = self.listView.defaultSize(with: .freeText, in: currentPage) if (pagePoint.x - defaultSize.width > 0){ pagePoint.x -= defaultSize.width; }else{ pagePoint.x = 0; } let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .freeText, selection: nil, page: currentPage, bounds: bounds) // self.view.window?.makeFirstResponder() if ((annotation) != nil) { // self.listView.updateActiveAnnotations([annotation!]) self.listView.edit(annotation) } case 2: // self.listView.annotationType = CAnnotationType.anchored let defaultSize = self.listView.defaultSize(with: .anchored, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .anchored, selection: nil, page: currentPage, bounds: bounds) self.listView.edit(annotation) case 3: // self.listView.annotationType = CAnnotationType.square let defaultSize = self.listView.defaultSize(with: .square, in: currentPage) if (pagePoint.x - defaultSize.width > 0){ pagePoint.x -= defaultSize.width; }else{ pagePoint.x = 0; } let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .square, selection: nil, page: currentPage, bounds: bounds) case 4: // self.listView.annotationType = CAnnotationType.circle let defaultSize = self.listView.defaultSize(with: .circle, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .circle, selection: nil, page: currentPage, bounds: bounds) case 5: // self.listView.annotationType = CAnnotationType.arrow let defaultSize = self.listView.defaultSize(with: .arrow, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .arrow, selection: nil, page: currentPage, bounds: bounds) case 6: // self.listView.annotationType = CAnnotationType.line let defaultSize = self.listView.defaultSize(with: .line, in: currentPage) let bounds = CPDFListViewRectFromCenterAndSize(CPDFListViewIntegralPoint(pagePoint), defaultSize) annotation = self.listView.addAnnotation(with: .line, selection: nil, page: currentPage, bounds: bounds) case 7: self.listView.annotationType = CAnnotationType.link self.openRightPane() case 8: self.listView.annotationType = CAnnotationType.stamp self.openRightPane() case 9: self.listView.annotationType = CAnnotationType.signSignature self.openRightPane() case 10: self.addImgAnnotationToView(center: pagePoint) default: break } self.rightSideViewController.isHidden = false self.rightSideViewController.subViewType = .AnnotationProperts if annotation != nil{ self.listView.activeAnnotations.removeAllObjects() // self.listView.activeAnnotations.add(annotation as Any) var newAnnonations : [CPDFAnnotation] = [] newAnnonations.append(annotation!) self.listView.updateActiveAnnotations(newAnnonations) // self.openRightPane() } // self.rightSideViewController.view.isHidden = false } // if (annotation != nil) { // self.listView.updateIsRightActiveAnnotations([annotation!]) // } } } func addImgAnnotationToView(center: NSPoint) { let accessoryCtr = KMImageAccessoryController() let openPanel = NSOpenPanel() openPanel.allowedFileTypes = KMImageAccessoryController.supportedImageTypes() openPanel.allowsMultipleSelection = false openPanel.accessoryView = accessoryCtr.view openPanel.isAccessoryViewDisclosed = true openPanel.beginSheetModal(for: self.view.window!) { result in if result == .OK { let fileURL = openPanel.urls.first let filePath = fileURL!.path if filePath.pathExtension == "pdf" { let pdf = CPDFDocument(url: fileURL) if pdf!.isEncrypted { NSSound.beep() return } } let img = NSImage(contentsOfFile: filePath) let isRemoveBGColor = accessoryCtr.selectedButton.state == .on self.listView.addImageAnnotation(img, center: center, isRemoveBGColor: isRemoveBGColor) } } } @objc func menuItemBookMarkClick_add(sender:NSMenuItem) { if self.listView?.document?.bookmark(forPageIndex: UInt(self.listView.currentPageIndex)) == nil { let index = self.listView.currentPageIndex self.listView?.document?.addBookmark("\(NSLocalizedString("Page", comment: "")) \(index+1)", forPageIndex: UInt(index)) self.listView?.setNeedsDisplayForVisiblePages() } else { self.listView?.document?.removeBookmark(forPageIndex: UInt(self.listView.currentPageIndex)) self.listView?.setNeedsDisplayForVisiblePages() } self.setDocumentEditedState(window: self.view.window) if self.isReadMode { } else { self.leftSideViewController.showBookmarkTab() } } @objc func menuItemAnnotationClick_FindString(sender:NSMenuItem) { self.leftSideViewController.refreshMethodType(methodType: .Search) } @objc func menuItemAnnotationClick_Print(sender:NSMenuItem) { let rect = listView.currentSelectionRect() let page = listView.currentPage() let copyPage : CPDFPage = page!.copy() as! CPDFPage copyPage.setBounds(rect, for: .cropBox) let image : NSImage = copyPage.thumbnail(of:(copyPage.bounds(for: .cropBox)).size) // let pdfDocument : PDFDocument = PDFDocument() // let newpage : PDFPage = PDFPage(image: image)! // pdfDocument.insert(newpage, at: 0) // 执行右键操作后,需要取消框选区域 if self.listView.toolMode == .selectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } if (self.listView.document != nil && !self.listView.document.allowsPrinting) { // 有打印限制 KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: self.listView.document.documentURL) { [weak self] result ,password in if (result == .cancel) { return } // 解除权限 self?.model.isSaveKeyChain = false self?.listView.document.unlock(withPassword: password) // 隐藏提示 self?.hiddenSecureLimitTip() // 去打印 KMPrintWindowController.printImage(image: image) } return } KMPrintWindowController.printImage(image: image) } // MARK: - Measure @objc func menuItemActionMeasureProperty(sender: NSMenuItem) { guard let anno = sender.representedObject as? CPDFAnnotation else { return } if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.hideFloatingWindow() } else if perimeterMeasureInfoWindowController?.window?.isVisible == true { perimeterMeasureInfoWindowController?.hideFloatingWindow() } else if areaMeasureInfoWindowController?.window?.isVisible == true { areaMeasureInfoWindowController?.hideFloatingWindow() } self.listView.updateActiveAnnotations([anno]) self.pdfListViewChangeatioActiveAnnotations(self.listView, forActiveAnnotations: [anno], isRightMenu: false) self.listView.setNeedsDisplayForVisiblePages() } @objc func menuItemActionMeasureEditNote(sender: NSMenuItem) { guard let anno = sender.representedObject as? CPDFAnnotation else { return } self.listView.edit(anno) } @objc func menuItemActionMeasureSetting(sender: NSMenuItem) { guard let anno = sender.representedObject as? CPDFAnnotation else { return } self.listView.updateActiveAnnotations([anno]) self.listView.setNeedsDisplayForVisiblePages() if let data = anno as? CPDFLineAnnotation, data.isMeasure { self.showMeasureDistanceSettingWindow(measureInfo: data.measureInfo) } else if let data = anno as? CPDFPolylineAnnotation { self.showMeasurePerimeterSettingWindow(measureInfo: data.measureInfo) } else if let data = anno as? CPDFPolygonAnnotation { self.showMeasureAreaSettingWindow(measureInfo: data.measureInfo) } } @objc func menuItemActionMeasureDelete(sender: NSMenuItem) { guard let anno = sender.representedObject as? CPDFAnnotation else { return } self.listView.remove(anno) } func showMeasureDistanceSettingWindow(measureInfo: CPDFDistanceMeasureInfo?, hideInfoWindow: Bool = true) { guard let mInfo = measureInfo else { return } let winC = CDistanceSettingWindowController(distanceMeasureInfo: mInfo) if hideInfoWindow { self.distanceMeasureInfoWindowController?.hideFloatingWindow() } winC.delegate = self winC.startModal("") } func showMeasurePerimeterSettingWindow(measureInfo: CPDFPerimeterMeasureInfo?, hideInfoWindow: Bool = true) { guard let mInfo = measureInfo else { return } let winC = CDistanceSettingWindowController(perimeterMeasureInfo: mInfo) if hideInfoWindow { self.perimeterMeasureInfoWindowController?.hideFloatingWindow() } winC.delegate = self winC.startModal("") } func showMeasureAreaSettingWindow(measureInfo: CPDFAreaMeasureInfo?, hideInfoWindow: Bool = true) { guard let mInfo = measureInfo else { return } let winC = CAreaSettingWindowController(measureInfo: mInfo) if hideInfoWindow { self.areaMeasureInfoWindowController?.hideFloatingWindow() } winC.delegate = self winC.startModal("") } func splitView(withTag tag: Int) { if tag == 0 { self.listView.viewSplitMode = KMPDFViewSplitMode.horizontal self.singlePageScreen(isSinglePage: false, doublePagesScreen: false) } else if tag == 1 { self.listView.viewSplitMode = KMPDFViewSplitMode.vertical self.singlePageScreen(isSinglePage: false, doublePagesScreen: true) } else if tag == 2 { self.listView.viewSplitMode = KMPDFViewSplitMode.disable self.singlePageScreen(isSinglePage: true, doublePagesScreen: false) } self.listView.needsDisplay = true } // MARK: - 幻灯片 func fadeInFullScreenWindow(with backgroundColor: NSColor, level: Int) { let view: NSView = self.view.window!.firstResponder as! NSView if view.isDescendant(of: pdfSplitView){ self.view.window?.makeFirstResponder(nil) } self.mainWindow = self.view.window let fullScreenWindow = KMFullScreenWindow(screen: (self.mainWindow?.screen ?? NSScreen.main)!, bgColor: backgroundColor, level: NSWindow.Level.popUpMenu.rawValue, isMain: true) fullScreenWindow.interactionParent = self.view.window self.mainWindow?.delegate = nil fullScreenWindow.fadeInBlocking() self.browserWindowController?.window = fullScreenWindow fullScreenWindow.makeKey() // NSApp.updatePresentationOptions(for: fullScreenWindow) let sel = NSSelectorFromString("setAnimationBehavior:") if self.mainWindow?.responds(to: sel) ?? false{ self.mainWindow?.animationBehavior = .none } self.mainWindow?.orderOut(nil) if self.mainWindow?.responds(to: sel) ?? false{ self.mainWindow?.animationBehavior = .default } fullScreenWindow.level = NSWindow.Level(rawValue: level) fullScreenWindow.orderFront(nil) // NSApp.addWindowsItem(fullScreenWindow, title: windowTitleForDocumentDisplayName(self.document?.displayName) ?? "", filename: false) } func fadeInFullScreenView(_ view: NSView, inset: CGFloat) { guard let fullScreenWindow = self.browserWindowController?.window as? KMFullScreenWindow else { return } let fadeWindow = KMFullScreenWindow(screen: fullScreenWindow.screen!, bgColor: fullScreenWindow.backgroundColor, level: fullScreenWindow.level.rawValue, isMain: false) fadeWindow.order(.above, relativeTo: fullScreenWindow.windowNumber) view.frame = NSInsetRect(fullScreenWindow.contentView?.bounds ?? .zero, inset, 0) fullScreenWindow.contentView?.addSubview(view) self.listView.layoutDocumentView() self.listView.requiresDisplay() fullScreenWindow.makeFirstResponder(self.listView) fullScreenWindow.recalculateKeyViewLoop() fullScreenWindow.delegate = self.browserWindowController // if (RUNNING_BEFORE(10_7)) // [fullScreenWindow display]; fullScreenWindow.display() fadeWindow.fadeOut() } // MARK: Redact 【密文标记】 @objc func redact_menuItemClick_delete(sender: NSMenuItem?) { self.listView.remove(self.listView.activeAnnotation) } @objc func redact_menuItemClick_setProperty(sender: NSMenuItem?) { let windowController = KMRedactPropertyWindowController(windowNibName: "KMRedactBaseWindowController") windowController.annotation = (self.listView.activeAnnotation as! CPDFRedactAnnotation) self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController windowController.itemClick = { [weak self] index, value in if (index == 1) { /// 取消 self?.view.window?.endSheet((self?.currentWindowController.window)!) self?.currentWindowController = nil return } let windowController_redact = self?.currentWindowController as! KMRedactPropertyWindowController let annotaton: CPDFRedactAnnotation = self?.listView.activeAnnotation as! CPDFRedactAnnotation annotaton.setBorderColor(windowController_redact.outsideColor) annotaton.setInteriorColor(windowController_redact.fillColor) if (windowController_redact.isOver) { annotaton.setFontColor(windowController_redact.fontColor) annotaton.setAlignment(windowController_redact.aligement) annotaton.setFont(windowController_redact.font) annotaton.setOverlayText(windowController_redact.overText) } self?.view.window?.endSheet((self?.currentWindowController.window)!) self?.currentWindowController = nil } } @objc func redact_menuItemClick_setCurrentPropertyToDefaultValue(sender: NSMenuItem?) { if (self.listView.activeAnnotation == nil || (self.listView.activeAnnotation.isKind(of: CPDFRedactAnnotation.self)) == false) { return } let annotation: CPDFRedactAnnotation = self.listView.activeAnnotation as! CPDFRedactAnnotation let model = CPDFAnnotationModel(annotationType: .redact) model?.setColor(annotation.borderColor()) model?.setInteriorColor(annotation.interiorColor()) let overlayText: String = annotation.overlayText() if (overlayText.isEmpty) { model?.setIsOverlayText(false) } else { model?.setIsOverlayText(true) model?.setOverlayText(overlayText) model?.setFontColor(annotation.fontColor()) model?.setAlignment(annotation.alignment()) model?.setFontName(annotation.font().fontName) model?.setFontSize(annotation.font().pointSize) } } @objc func redact_menuItemClick_MultiPageFlag(sender: NSMenuItem?) { let anno = self.listView.activeAnnotation if (anno == nil || (anno?.isKind(of: CPDFRedactAnnotation.self)) == false) { return } let windowController = KMRedactMutilPageFlagWindowController(windowNibName: "KMRedactBaseWindowController") windowController.pageCount = Int(self.listView.document?.pageCount ?? 0) self.currentWindowController = windowController self.view.window?.beginSheet(windowController.window!) windowController.itemClick = { [weak self] index, value in if (index == 1) { self!.view.window?.endSheet(self!.currentWindowController.window!) self!.currentWindowController = nil return } let windowController_mutilPageFlag = self?.currentWindowController as! KMRedactMutilPageFlagWindowController let pageType = windowController_mutilPageFlag.pageType let pageString = windowController_mutilPageFlag.pageString if (pageType == 4) { /// 自定义页面 let array = KMPageRangeTools.findSelectPage(pageRangeString: pageString, pageCount: Int((self?.listView.document?.pageCount) ?? 0)) if (array.count == 0) { let alert = NSAlert() alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "") alert.runModal() return } } self!.view.window?.endSheet(self!.currentWindowController.window!) self!.currentWindowController = nil let indexs = KMRedactTools.getPageIndexs(pageType, string: pageString, Int((self?.listView.document?.pageCount) ?? 0)) if (indexs.count == 0) { return } for i in indexs { let page: CPDFPage = (self?.listView.document?.page(at: UInt(i)))! let redactAnno = KMRedactTools.createRedactAnnotation((self?.listView.document)!, anno as! CPDFRedactAnnotation) self?.listView.add(redactAnno, to: page) } } } @objc func redact_menuItemClick_apply(sender: NSMenuItem?) { self.exeRedactConfirm(.redactOne) {} } @objc func redact_menuItemClick_clear(sender: NSMenuItem?) { self.exeRedactConfirm(.eraserOne) {} } @objc func redact_menuItemClick_paste(sender: NSMenuItem?) { } @objc func exportStampImage(sender:NSMenuItem) { if listView.activeAnnotation != nil && ((listView.activeAnnotation is CPDFStampAnnotation) || (listView.activeAnnotation is CPDFSignatureAnnotation)) || (self.listView.selectImageAreas != nil) { var image : NSImage = NSImage() if (listView.activeAnnotation is CPDFStampAnnotation) { image = (listView.activeAnnotation as! CPDFStampAnnotation).stampImage() } else if (listView.activeAnnotation is CPDFSignatureAnnotation) { image = (listView.activeAnnotation as! CPDFSignatureAnnotation).signImage } else { image = self.listView.selectImageAreas.thumbnailImage(with: CGSize(width: 1920, height: 1920)) ?? NSImage() } let data = image.tiffRepresentation if sender.tag == 0 { let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data!) ?? NSBitmapImageRep() imageRep.size = image.size let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])! let savePanel = NSSavePanel() savePanel.allowedFileTypes = ["png"] savePanel.beginSheetModal(for: self.view.window!) { response in if (response != .OK) { return } if NSData(data: imageData).write(to: savePanel.url!, atomically: true) { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: ""); } } } else { let pdfdocument = CPDFDocument() let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png") if NSData(data: data!).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) { pdfdocument?.km_insertPage(image.size, withImage: signatureImagePath!, at: 0) let savePanel = NSSavePanel() savePanel.allowedFileTypes = ["pdf"] savePanel.beginSheetModal(for: self.view.window!) { response in if (response != .OK) { return } if pdfdocument!.write(to: savePanel.url!) { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: ""); } } } } } } @objc func exportCorpImage(sender:NSMenuItem) { let rect = NSIntegralRect(listView.currentSelectionRect()) let orgPage : CPDFPage = listView.currentSelectionPage() ?? listView.currentPage() let page : CPDFPage = orgPage.copy() as! CPDFPage page.setBounds(rect, for: .cropBox) let image = page.thumbnail(of: rect.size) ?? NSImage() let data = image.tiffRepresentation guard let data = data else { return } let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data) ?? NSBitmapImageRep() imageRep.size = rect.size let savePanel = NSSavePanel() switch sender.tag { case 0: savePanel.allowedFileTypes = ["png"] let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])! savePanel.beginSheetModal(for: self.view.window!) { response in if (response != .OK) { return } if NSData(data: imageData).write(to: savePanel.url!, atomically: true) { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: ""); } } case 1: savePanel.allowedFileTypes = ["jpg"] let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])! savePanel.beginSheetModal(for: self.view.window!) { response in if (response != .OK) { return } if NSData(data: imageData).write(to: savePanel.url!, atomically: true) { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: ""); } } case 2: savePanel.allowedFileTypes = ["pdf"] let pdfdocument = CPDFDocument() let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png") let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])! if NSData(data: imageData).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) { pdfdocument?.insertPage(image.size, withImage: signatureImagePath, at: 0) savePanel.beginSheetModal(for: self.view.window!) { response in if (response != .OK) { return } if pdfdocument!.write(to: savePanel.url!) { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: ""); } } } default: break } // 执行右键操作后,需要取消框选区域 if self.listView.toolMode == .selectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } } @IBAction func doZoomToAutoSelection(sender:NSMenuItem) { let rect = listView.currentSelectionRect() let page = listView.currentPage() if NSIsEmptyRect(rect) == false && page != nil { let isLegacy = NSScroller.responds(to: NSSelectorFromString("preferredScrollerStyle")) == false || NSScroller.preferredScrollerStyle == .legacy var bounds = listView.bounds var scale = 1.0 if isLegacy { bounds.size.width -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle) bounds.size.height -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle) } if NSWidth(bounds) * NSHeight(rect) > NSWidth(rect) * NSHeight(bounds) { scale = NSHeight(bounds) / NSHeight(rect) } else { scale = NSWidth(bounds) / NSWidth(rect) } listView.setScaleFactor(scale, animated: false) let scrollView = listView.scroll() if isLegacy && scrollView?.hasHorizontalScroller == false || scrollView?.hasVerticalScroller == false { if ((scrollView?.hasVerticalScroller) != nil) { bounds.size.width -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle) } if ((scrollView?.hasHorizontalScroller) != nil) { bounds.size.height -= NSScroller.scrollerWidth(for: .regular, scrollerStyle: listView.documentView().scrollerStyle) } if NSWidth(bounds) * NSHeight(rect) > NSWidth(rect) * NSHeight(bounds) { scale = NSHeight(bounds) / NSHeight(rect) } else { scale = NSWidth(bounds) / NSWidth(rect) } listView.setScaleFactor(scale, animated: false) } DispatchQueue.main.asyncAfter(deadline: .now() + 0.03) { [self] in let pagePoint = CGPoint(x: rect.origin.x, y: (rect.origin.y + rect.size.height)) listView.go(toTargetPoint: pagePoint, on: page, at: .top) }; } // 执行右键操作后,需要取消框选区域 if self.listView.toolMode == .selectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } } private func cropPagesToRects(rects:NSPointerArray) { } @IBAction func defaultAnnotationPorpert(sender:NSMenuItem) { let model : CPDFAnnotationModel = CPDFAnnotationModel(annotationType: CAnnotationType(rawValue: sender.tag)!)! switch sender.tag { case CAnnotationType.highlight.rawValue,CAnnotationType.underline.rawValue,CAnnotationType.strikeOut.rawValue: model.setColor((listView.activeAnnotation as! CPDFMarkupAnnotation).color) model.setOpacity((listView.activeAnnotation as! CPDFMarkupAnnotation).opacity) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFMarkupAnnotation).color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) if sender.tag == CAnnotationType.highlight.rawValue { KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFMarkupAnnotation).opacity], forKey: KMPreference.markupColorHighlightKey) } else if sender.tag == CAnnotationType.underline.rawValue { KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFMarkupAnnotation).opacity], forKey: KMPreference.markupColorUnderlineKey) } else if sender.tag == CAnnotationType.strikeOut.rawValue { KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFMarkupAnnotation).opacity], forKey: KMPreference.markupColorStrikthroughKey) } case CAnnotationType.ink.rawValue: model.setColor((listView.activeAnnotation as! CPDFInkAnnotation).color) model.setOpacity((listView.activeAnnotation as! CPDFInkAnnotation).opacity) model.setLineWidth((listView.activeAnnotation as! CPDFInkAnnotation).lineWidth()) model.setStyle((listView.activeAnnotation as! CPDFInkAnnotation).borderStyle()) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFInkAnnotation).color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFInkAnnotation).opacity], forKey: KMPreference.markupColorPenKey) case CAnnotationType.freeText.rawValue: model.setColor((listView.activeAnnotation as! CPDFFreeTextAnnotation).color) model.setOpacity((listView.activeAnnotation as! CPDFFreeTextAnnotation).opacity) model.setFontColor((listView.activeAnnotation as! CPDFFreeTextAnnotation).fontColor) model.setFontName((listView.activeAnnotation as! CPDFFreeTextAnnotation).font.fontName) model.setFontSize((listView.activeAnnotation as! CPDFFreeTextAnnotation).font.pointSize) model.setAlignment((listView.activeAnnotation as! CPDFFreeTextAnnotation).alignment) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFFreeTextAnnotation).fontColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFFreeTextAnnotation).opacity], forKey: KMPreference.markupColorTextKey) if (KMPreferenceManager.supportFonts.contains((listView.activeAnnotation as! CPDFFreeTextAnnotation).font.fontName)) { UserDefaults.standard.set((listView.activeAnnotation as! CPDFFreeTextAnnotation).font.fontName, forKey: KMPreference.markupFontTextStringKey) UserDefaults.standard.synchronize() } let alignment = (listView.activeAnnotation as! CPDFFreeTextAnnotation).alignment if (alignment == .left || alignment == .center || alignment == .right) { UserDefaults.standard.set(alignment.rawValue, forKey: KMPreference.markupFontTextAligmentKey) UserDefaults.standard.synchronize() } case CAnnotationType.anchored.rawValue: model.setColor((listView.activeAnnotation as! CPDFTextAnnotation).color) model.setAnchoredIconType((listView.activeAnnotation as! CPDFTextAnnotation).iconType()) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFTextAnnotation).color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, alpha], forKey: KMPreference.markupColorNoteKey) case CAnnotationType.square.rawValue: model.setInteriorColor((listView.activeAnnotation as! CPDFSquareAnnotation).interiorColor) model.setColor((listView.activeAnnotation as! CPDFSquareAnnotation).color) model.setOpacity((listView.activeAnnotation as! CPDFSquareAnnotation).opacity) model.setLineWidth((listView.activeAnnotation as! CPDFSquareAnnotation).lineWidth()) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFSquareAnnotation).interiorColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFSquareAnnotation).interiorOpacity], forKey: KMPreference.markupColorRectangleFillKey) (listView.activeAnnotation as! CPDFSquareAnnotation).color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFSquareAnnotation).opacity], forKey: KMPreference.markupColorRectangleBorderKey) case CAnnotationType.circle.rawValue: model.setInteriorColor((listView.activeAnnotation as! CPDFCircleAnnotation).interiorColor) model.setColor((listView.activeAnnotation as! CPDFCircleAnnotation).color) model.setOpacity((listView.activeAnnotation as! CPDFCircleAnnotation).opacity) model.setLineWidth((listView.activeAnnotation as! CPDFCircleAnnotation).lineWidth()) var red: CGFloat = 0.0 var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 0.0 (listView.activeAnnotation as! CPDFCircleAnnotation).interiorColor.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFCircleAnnotation).interiorOpacity], forKey: KMPreference.markupColorCircleFillKey) (listView.activeAnnotation as! CPDFCircleAnnotation).color.usingColorSpaceName(.calibratedRGB)?.getRed(&red, green: &green, blue: &blue, alpha: &alpha) KMPreferenceManager.shared.setData(data: [red, green, blue, (listView.activeAnnotation as! CPDFCircleAnnotation).opacity], forKey: KMPreference.markupColorCircleBorderKey) default: break } } @objc internal func menuItemClick_HidenorShowNote(sender: NSMenuItem?) { self.showOrHideNotes() } //MARK: - action @objc func cropCurrentPage() { var rect = NSIntegralRect(self.listView.currentSelectionRect()) var page: CPDFPage? if let data = self.listView.currentSelectionPage() { page = data } else { page = self.listView.currentPage() } if (NSIsEmptyRect(rect)) { rect = KMCropTools.getPageForegroundBox(page!) } let index: UInt = (page?.pageIndex()) ?? 0 self._cropPage(at: index, in: rect) // 执行右键操作后,需要取消框选区域 if self.listView.toolMode == .selectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } self.handlePageBoundsDidChange(page: page, action: CPDFPage.Action.crop) } @objc private func _cropPage(at index: UInt, in rect: NSRect) { let oldRect = self.listView?.document?.page(at: index)?.bounds(for: .cropBox) ?? .zero let undoManager = self.listView.undoManager (undoManager?.prepare(withInvocationTarget: self) as? AnyObject)?._cropPage(at: index, in: oldRect) let page = self.listView.document.page(at: index) let newRect = NSIntersectionRect(rect, (page?.bounds(for: .mediaBox)) ?? .zero) page?.setBounds(newRect, for: .cropBox) /// 刷新预览视图 self.listView.layoutDocumentView() self.listView.displayBox = .cropBox } func beginProgressSheet(with message: String, maxValue: UInt) { let progress = SKProgressController() // progress.window?.backgroundColor = NSColor.km_init(hex: "#ffffff") progress.window?.contentView?.wantsLayer = true // progress.window?.contentView?.layer?.backgroundColor = NSColor.km_init(hex: "#ffffff").cgColor // progress.progressField.textColor = NSColor.black progress.message = NSLocalizedString("Converting...", comment: "") self.progressC = progress self.progressC?.message = message if maxValue > 0 { progressC?.indeterminate = false progressC?.maxValue = Double(maxValue) } else { progressC?.indeterminate = true } self.view.km_beginSheet(windowC: progressC!) } // 白边距 @objc func smart_cropAllPage() { var size = NSZeroSize for i in 0 ..< self.listView.document.pageCount { let page = self.listView.document.page(at: i) let rect = KMCropTools.getPageForegroundBox(page!) size.width = fmax(size.width, NSWidth(rect)) size.height = fmax(size.height, NSHeight(rect)) } beginProgressSheet(with: KMLocalizedString("Cropping Pages", "Message for progress sheet"), maxValue: min(18, self.listView.document.pageCount)) var rectArray: Array = [] for i in 0 ..< self.listView.document.pageCount { progressC?.increment(by: Double(i)) progressC?.doubleValue = Double(i) let page = self.listView.document.page(at: i) var rect = KMCropTools.getPageForegroundBox(page!) let bounds: NSRect = (page?.bounds(for: .mediaBox))! // if (rect.minX - bounds.minX > bounds.maxX-rect.maxX) { // rect.origin.x = rect.maxX-size.width // } // rect.origin.y = rect.maxY-size.height // rect.size = size // if (NSWidth(rect) > NSWidth(bounds)) { // rect.size.width = NSWidth(bounds) // } // if (NSHeight(rect) > NSHeight(bounds)) { // rect.size.height = NSHeight(bounds) // } // // if (NSMinX(rect) < NSMinX(bounds)) { // rect.origin.x = NSMinX(bounds) // } else if (NSMaxX(rect) > NSMaxX(bounds)) { // rect.origin.x = NSMaxX(bounds) - NSWidth(rect) // } // // if (NSMinY(rect) < NSMinY(bounds)) { // rect.origin.y = NSMinY(bounds) // } else if (NSMaxY(rect) > NSMaxY(bounds)) { // rect.origin.y = NSMaxY(bounds) - NSHeight(rect) // } rectArray.append(rect) } cropPages(to: rectArray) self.handlePageBoundsDidChange(page: nil, action: CPDFPage.Action.crop) } // 自动 @objc func auto_cropAllPage() { var size = NSZeroSize for i in 0 ..< self.listView.document.pageCount { let page = self.listView.document.page(at: i) let rect = KMCropTools.getPageForegroundBox(page!) size.width = fmax(size.width, NSWidth(rect)) size.height = fmax(size.height, NSHeight(rect)) } beginProgressSheet(with: KMLocalizedString("Cropping Pages", "Message for progress sheet"), maxValue: min(18, self.listView.document.pageCount)) var rectArray: Array = [] for i in 0 ..< self.listView.document.pageCount { progressC?.increment(by: Double(i)) progressC?.doubleValue = Double(i) let page = self.listView.document.page(at: i) var rect = KMCropTools.getPageForegroundBox(page!) let bounds: NSRect = (page?.bounds(for: .mediaBox))! if (rect.minX - bounds.minX > bounds.maxX-rect.maxX) { rect.origin.x = rect.maxX-size.width } rect.origin.y = rect.maxY-size.height rect.size = size if (NSWidth(rect) > NSWidth(bounds)) { rect.size.width = NSWidth(bounds) } if (NSHeight(rect) > NSHeight(bounds)) { rect.size.height = NSHeight(bounds) } if (NSMinX(rect) < NSMinX(bounds)) { rect.origin.x = NSMinX(bounds) } else if (NSMaxX(rect) > NSMaxX(bounds)) { rect.origin.x = NSMaxX(bounds) - NSWidth(rect) } if (NSMinY(rect) < NSMinY(bounds)) { rect.origin.y = NSMinY(bounds) } else if (NSMaxY(rect) > NSMaxY(bounds)) { rect.origin.y = NSMaxY(bounds) - NSHeight(rect) } rectArray.append(rect) } cropPages(to: rectArray) self.handlePageBoundsDidChange(page: nil, action: CPDFPage.Action.crop) } @objc func cropAllPage() { var rect = [NSIntegralRect(self.listView?.currentSelectionRect() ?? .zero), .zero] var rectArray: Array = [] let emptySelection = NSIsEmptyRect(rect.first ?? .zero) if (emptySelection) { guard let count = self.listView?.document?.pageCount, count > 0 else { KMPrint("listView | document is nil.", beep: true) return } rect[0] = .zero rect[1] = .zero self.beginProgressSheet(withMessage: NSLocalizedString("Cropping Pages", comment: "Message for progress sheet"), maxValue: min(18, count)) if (count == 1) { if let page = self.listView.document.page(at: 0) { rect[0] = KMCropTools.getPageForegroundBox(page) } progressC?.increment(by: 1) } else if (count < 19) { for i in 0 ..< 19 { if let page = self.listView.document.page(at: UInt(i)) { rect[i % 2] = NSUnionRect(rect[i % 2], KMCropTools.getPageForegroundBox(page)) progressC?.increment(by: Double(i)) } } } else { let start = [1, (count - 5) / 2, count - 6] var cnt = 0 for j in 0 ..< 3 { for i in 0 ..< 6 { let k = Int(start[j] + UInt(i)) if let page = self.listView.document.page(at: UInt(k)) { rect[k % 2] = NSUnionRect(rect[k % 2], KMCropTools.getPageForegroundBox(page)) cnt += 1 progressC?.increment(by: Double(cnt)) } } } } let w = fmax(NSWidth(rect[0]), NSWidth(rect[1])) let h = fmax(NSHeight(rect[0]), NSHeight(rect[1])) for j in 0 ..< 2 { rect[j] = NSMakeRect(floor(NSMidX(rect[j]) - 0.5 * w), floor(NSMidY(rect[j]) - 0.5 * h), w, h) } rectArray.append(rect.first ?? .zero) rectArray.append(rect.last ?? .zero) } else { rectArray.append(rect.first ?? .zero) } self.cropPages(to: rectArray) // 执行右键操作后,需要取消框选区域 if self.listView.toolMode == .selectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } self.handlePageBoundsDidChange(page: nil, action: CPDFPage.Action.crop) } func cropPages(to rects: Array) { let currentPage = self.listView.currentPage() let visibleRect: NSRect = self.listView.convert(self.listView.convert(self.listView.documentView().visibleRect, from: self.listView.documentView()), to: self.listView.currentPage()) var oldRectArray: Array = [] let rectCount = rects.count for i in 0 ..< self.listView.document.pageCount { let page = self.listView.document.page(at: i) let rect = NSIntersectionRect(rects[Int(i) % rectCount], (page?.bounds(for: .mediaBox))!) let oldRect = page?.bounds(for: .cropBox) oldRectArray.append(oldRect!) page?.setBounds(rect, for: .cropBox) } let undoManager = self.listView.undoManager (undoManager?.prepare(withInvocationTarget: self) as AnyObject).cropPages(to: oldRectArray) /// 刷新预览视图 self.listView.layoutDocumentView() self.listView.displayBox = .cropBox self.listView.go(to: currentPage) self.listView.go(to: visibleRect, on: currentPage) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [self] in self.dismissProgressSheet() } } @objc private func shareDocument(sender:KMToolbarViewController, limit: Bool = false) { if (limit) { let document = self.listView.document ?? CPDFDocument() if document?.documentURL == nil { return } var doucumentURL : URL = self.listView.document.documentURL if doucumentURL.path.count > 0 { let docDir = NSTemporaryDirectory() let documentName : String = doucumentURL.path.lastPathComponent let path = docDir.stringByAppendingPathComponent(documentName) // let writeSuccess = self.listView.document.write(to: URL(fileURLWithPath: path)) let data = KMTools.saveWatermarkDocument(document: self.listView.document, to: URL(fileURLWithPath: path), secureOptions: self.secureOptions, removePWD: self.removeSecureFlag) let writeSuccess = data != nil if writeSuccess == false { __NSBeep() return; } doucumentURL = URL(fileURLWithPath: path) } let array = [doucumentURL] let picker = NSSharingServicePicker.init(items: array) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } return } let document = self.listView.document ?? CPDFDocument() if document?.documentURL == nil { return } var doucumentURL : URL = self.listView.document.documentURL if doucumentURL.path.count > 0 { let docDir = NSTemporaryDirectory() let documentName : String = doucumentURL.path.lastPathComponent let path = docDir.stringByAppendingPathComponent(documentName) let writeSuccess = self.listView.document.write(to: URL(fileURLWithPath: path)) if writeSuccess == false { __NSBeep() return; } doucumentURL = URL(fileURLWithPath: path) } let array = [doucumentURL] let picker = NSSharingServicePicker.init(items: array) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } } @objc private func shareFlatten(sender:KMToolbarViewController, limit: Bool = false) { if (limit) { let document = self.listView.document ?? CPDFDocument() var path: String? if document?.documentURL != nil { path = document?.documentURL.path ?? "" } if path?.count ?? 0 > 0 { let docDir = NSTemporaryDirectory() let documentName : String = path?.lastPathComponent ?? "" path = docDir.stringByAppendingPathComponent(documentName) } let pathFolder = path?.fileURL.deletingLastPathComponent().path var tfileName = path?.deletingPathExtension.lastPathComponent let tStdFileSuffix = "_flatten" tfileName = (tfileName ?? "") + tStdFileSuffix + ".pdf" path = (pathFolder ?? "") + "/" + (tfileName ?? "") let data = KMTools.saveWatermarkDocumentForFlatten(document: document!, to: URL(fileURLWithPath: path ?? "")) let success = data != nil if success { let url = URL(fileURLWithPath: path ?? "") let picker = NSSharingServicePicker.init(items: [url]) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } } return } let document = self.listView.document ?? CPDFDocument() var path: String? if document?.documentURL != nil { path = document?.documentURL.path ?? "" } if path?.count ?? 0 > 0 { let docDir = NSTemporaryDirectory() let documentName : String = path?.lastPathComponent ?? "" path = docDir.stringByAppendingPathComponent(documentName) } let pathFolder = path?.fileURL.deletingLastPathComponent().path var tfileName = path?.deletingPathExtension.lastPathComponent let tStdFileSuffix = "_flatten" tfileName = (tfileName ?? "") + tStdFileSuffix + ".pdf" path = (pathFolder ?? "") + "/" + (tfileName ?? "") let success : Bool = document?.writeFlatten(to: URL(fileURLWithPath: path ?? "")) ?? false if success { let url = URL(fileURLWithPath: path ?? "") let picker = NSSharingServicePicker.init(items: [url]) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } } } @objc private func shareOriginalPDF(sender:KMToolbarViewController, limit: Bool = false) { guard let pdfDoc = self.listView.document else { NSSound.beep() return } if !pdfDoc.allowsCopying || !pdfDoc.allowsPrinting { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } if (limit) { let document = self.listView.document ?? CPDFDocument() var path: String? if document?.documentURL != nil { path = document?.documentURL.path ?? "" } if path?.count ?? 0 > 0{ let docDir = NSTemporaryDirectory() let documentName : String = path?.lastPathComponent ?? "" path = docDir.stringByAppendingPathComponent(documentName) } // var writeSuccess = document!.write(to: URL(fileURLWithPath: path)) let data = KMTools.saveWatermarkDocument(document: document!, to: URL(fileURLWithPath: path ?? ""), secureOptions: self.secureOptions, removePWD: self.removeSecureFlag) var writeSuccess = data != nil if writeSuccess == false { __NSBeep() return; } let newDocument = CPDFDocument(url: URL(fileURLWithPath: path ?? "")) let cnt = newDocument?.pageCount ?? 0 for i in 0 ..< cnt { let page = newDocument?.page(at: i) var annotations : [CPDFAnnotation] = [] for annotation in page!.annotations { annotations.append(annotation) } for annotation in annotations { annotation.page.removeAnnotation(annotation) } } writeSuccess = newDocument?.write(to:URL(fileURLWithPath: path ?? "")) ?? false if writeSuccess { let url = URL(fileURLWithPath: path ?? "") let picker = NSSharingServicePicker.init(items: [url]) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } } return } let document = self.listView.document ?? CPDFDocument() var path: String? if document?.documentURL != nil { path = document?.documentURL.path ?? "" } if path?.count ?? 0 > 0 { let docDir = NSTemporaryDirectory() let documentName : String = path?.lastPathComponent ?? "" path = docDir.stringByAppendingPathComponent(documentName) } var writeSuccess = document?.write(to: URL(fileURLWithPath: path ?? "")) if writeSuccess == false { __NSBeep() return; } let newDocument = CPDFDocument(url: URL(fileURLWithPath: path ?? "")) let cnt = newDocument?.pageCount ?? 0 for i in 0 ..< cnt { let page = newDocument!.page(at: i) var annotations : [CPDFAnnotation] = [] for annotation in page!.annotations { annotations.append(annotation) } for annotation in annotations { annotation.page.removeAnnotation(annotation) } } writeSuccess = newDocument?.write(to:URL(fileURLWithPath: path ?? "")) if writeSuccess ?? false { let url = URL(fileURLWithPath: path ?? "") let picker = NSSharingServicePicker.init(items: [url]) if sender.shareButton.window != nil { picker.show(relativeTo: sender.shareButton.bounds, of: sender.shareButton, preferredEdge: NSRectEdge.minY) } else { picker.show(relativeTo: NSRect(x: (self.view.window?.contentView?.frame.size.width)!, y: (self.view.window?.contentView?.frame.size.height ?? 0)-8, width: 0, height: 0), of: self.view.window?.contentView ?? NSView(), preferredEdge: NSRectEdge.minY) } } } // 开启/关闭左边栏 @objc func toggleLeftPane() -> Void { // if lastLeftPanWidth >= functionWidth { self.model.leftPanelOpen = true applyLeftSideWidth(self.model.panelWidth+functionWidth, rightSideWidth: self.model.lastRightPanWidth) // } else { // leftPanelOpen = false // applyLeftSideWidth(functionWidth, rightSideWidth: lastRightPanWidth) // } } // 开启左边栏 @objc func openLeftPane() -> Void { self.model.leftPanelOpen = true applyLeftSideWidth(self.model.panelWidth+functionWidth, rightSideWidth: self.model.lastRightPanWidth) self.toolbarController.findItem(KMLeftControlToolbarItemIdentifier)?.isSelected = true } // 关闭左边栏 @objc func closeLeftPane() -> Void { self.model.leftPanelOpen = false applyLeftSideWidth(functionWidth, rightSideWidth: self.model.lastRightPanWidth) self.toolbarController.findItem(KMLeftControlToolbarItemIdentifier)?.isSelected = false } // 开启/关闭右边栏 @objc func toggleRightPane() -> Void { if self.model.lastRightPanWidth > 5 { self.model.rightPanelIsOpen = false applyLeftSideWidth(self.model.lastLeftPanWidth, rightSideWidth: 0) } else { self.model.rightPanelIsOpen = true applyLeftSideWidth(self.model.lastLeftPanWidth, rightSideWidth: self.model.defaultRightWidth) } } @objc func openRightPane() -> Void { if (KMPreferenceManager.shared.autoExpandPropertyPanel) { if self.model.rightPanelIsOpen { return } self.model.rightPanelIsOpen = true self.toolbarController.selectItem(KMRightControlToolbarItemIdentifier) applyLeftSideWidth(self.model.lastLeftPanWidth, rightSideWidth: self.model.defaultRightWidth) } } @objc func closeRightPane() -> Void { if (KMPreferenceManager.shared.autoExpandPropertyPanel) { self.model.rightPanelIsOpen = false self.toolbarController.cancelSelected(KMRightControlToolbarItemIdentifier) applyLeftSideWidth(self.model.lastLeftPanWidth, rightSideWidth: 0) cancelMeasureType() } } func rename(_ sender: NSNotification) -> Void { if (self.view.window == nil || self.view.window!.isVisible == false) { return } let tabController = sender.object as? CTTabController if tabController?.title == self.document?.documentURL.deletingPathExtension().lastPathComponent { if let doc = self.myDocument, doc.isDocumentEdited { Task { let resp = await KMAlertTool.runModel(message: NSLocalizedString("File Updated", comment: ""), buttons: [NSLocalizedString("Save", comment: ""), NSLocalizedString("Cancel", comment: "")]) if resp != .alertFirstButtonReturn { // 取消 return } doc.updateChangeCount(.changeCleared) // doc.save(nil) self.document?.write(to: doc.fileURL) Task { @MainActor in self._renameForSavePanel(tabController) } } return } self._renameForSavePanel(tabController) } } func savePdfAlertView() { if AutoSaveManager.manager.isSaving || AutoSaveManager.manager.isSaveNoti{ return } AutoSaveManager.manager.isSaveNoti = true var num = 0 if self.listView.document != nil{ num = Int(self.listView.document.pageCount) } if Thread.current.isMainThread { self.beginProgressSheet(withMessage: NSLocalizedString("Saving PDF", comment: "") + "...", maxValue: UInt(num)) } else { DispatchQueue.main.async { self.beginProgressSheet(withMessage: NSLocalizedString("Saving PDF", comment: "") + "...", maxValue: UInt(num)) } } } func savePdfFinishAlertView() { if !AutoSaveManager.manager.isSaveNoti{ return } AutoSaveManager.manager.isSaveNoti = false if Thread.current.isMainThread { self.dismissProgressSheet() } else { DispatchQueue.main.async { self.dismissProgressSheet() } } } private func _renameForSavePanel(_ tabC: CTTabController?) { let outputSavePanel = NSSavePanel() outputSavePanel.title = NSLocalizedString("Rename", comment: "") outputSavePanel.allowedFileTypes = ["pdf"] outputSavePanel.nameFieldStringValue = (self.document?.documentURL.lastPathComponent)! outputSavePanel.directoryURL = self.document?.documentURL.deletingLastPathComponent() let resp = outputSavePanel.runModal() if resp == .OK { let pdfDocument = CPDFDocument(url: self.document?.documentURL) let fileURL = pdfDocument?.documentURL let fileManager = FileManager.default let newFileURL = fileURL!.deletingLastPathComponent().appendingPathComponent(outputSavePanel.url!.lastPathComponent) var result = true do { try fileManager.moveItem(at: fileURL!, to: newFileURL) } catch { result = false KMPrint("Error renaming file! Threw: \(error.localizedDescription)") } if (result) { tabC?.title = outputSavePanel.url!.lastPathComponent // self.myDocument?.fileURL = newFileURL if let newPdfDocument = CPDFDocument(url: newFileURL) { self.model.isSaveKeyChain = false newPdfDocument.unlock(withPassword: self.document?.password) if (newPdfDocument.pageCount > 0) { self.setDocument = newPdfDocument } } } } else { outputSavePanel.close() } } func showInFinder(_ sender: Any) -> Void { if sender is NSNotification { let tabController = (sender as! NSNotification).object as? CTTabController let path = self.document?.documentURL.deletingPathExtension().lastPathComponent if tabController?.title == path { if let file = self.myDocument?.fileURL { if FileManager.default.fileExists(atPath: file.path) { NSWorkspace.shared.activateFileViewerSelecting([file]) } } } } else { guard let url = self.myDocument?.fileURL else { return } let file: URL = url if FileManager.default.fileExists(atPath: file.path) { NSWorkspace.shared.activateFileViewerSelecting([file]) } } } func showOrHideNotes() { self.listView.hideNotes = !self.listView.hideNotes for note in self.listView.notes as? [CPDFAnnotation] ?? [] { if note.isForm() { note.setAnnotationShouldDisplay(true) note.setHidden(false) } } self.listView.setNeedsDisplayAnnotationViewForVisiblePages() self.toolbarController.isShowAllAnnotations = !self.listView.hideNotes //BOTA 注释列表显示隐藏 // self.leftSideViewController.annotationViewController.annotationShowState = self.listView.hideNotes ? .hidden : .none // self.leftSideViewController.thumbnailViewController.annotationShowState = self.listView.hideNotes ? .hidden : .none self.leftSideViewController.note_reloadDataIfNeed() } func closeTab(_ sender: NSNotification) -> Void { // let tabController = sender.object as? CTTabController // let path = self.document?.documentURL.deletingPathExtension().lastPathComponent // if tabController?.title == path { // print("closeTab") // self.leftSideViewController.clearAnnotationFilterData() // self.leftSideViewController.clearNotification() // } } @IBAction func toggleSplitPDF(_ sender: Any) { if let menuItem = sender as? NSMenuItem { splitView(withTag: menuItem.tag) } } @IBAction func readMode(_ sender: Any) { isReadMode = !isReadMode UserDefaults.standard.set(isReadMode, forKey: "kKMPDFViewIsReadMode") UserDefaults.standard.synchronize() if isReadMode { CustomAlertView.alertView(message: NSLocalizedString("Read Mode On", comment: ""), fromView: (view.window?.contentView)!, withStyle: .black) } else { CustomAlertView.alertView(message: NSLocalizedString("Read Mode Off", comment: ""), fromView: (view.window?.contentView)!, withStyle: .black) } } func handlePageBoundsDidChange(page: CPDFPage?, action: String) { // NSDictionary *info = [notification userInfo]; // PDFPage *page = [info objectForKey:SKPDFPagePageKey]; // NSString *action = [info objectForKey:SKPDFPageActionKey]; // BOOL displayChanged = [action isEqualToString:SKPDFPageActionCrop] == NO || [pdfView displayBox] == kPDFDisplayBoxCropBox; let displayChanged = action == CPDFPage.Action.crop || self.listView.displayBox == .cropBox // if self.listView.displayBox == .cropBox { // KMPrint("cropBox") // } else if self.listView.displayBox == .artBox { // KMPrint("artBox") // } else if self.listView.displayBox == .trimBox { // KMPrint("trimBox") // } else if self.listView.displayBox == .bleedBox { // KMPrint("bleedBox") // } else if self.listView.displayBox == .mediaBox { // KMPrint("mediaBox") // } else { // KMPrint("other \(self.listView.displayBox.rawValue)") // } if (displayChanged) { self.listView.layoutDocumentView() } if (page != nil) { let idx = page!.pageIndex() if (displayChanged) { self.leftSideViewController.updateThumbnail(at: Int(idx)) } } else { if (displayChanged) { self.leftSideViewController.allThumbnailsNeedUpdate() } } self.leftSideViewController.updateSnapshotsIfNeed(for: page) // [secondaryPdfView requiresDisplay]; self.secondaryPdfView?.setNeedsDisplayForVisiblePages() // if UserDefaults.standard.bool(forKey: SKDisplayPageBoundsKey) { // [self updateRightStatus]; } } func changeLineAttribute(_ sender: Any?) { var inspector = sender as? KMLineInspector if inspector == nil { inspector = KMLineInspector.shared } let action = inspector?.currentLineChangeAction ?? .no for annotation in self.listView.activeAnnotations { guard let anno = annotation as? CPDFAnnotation else { continue } if anno.hasBorder() { // if (mwcFlags.updatingLine == 0 && [annotation hasBorder]) { // mwcFlags.updatingLine = 1; switch (action) { case .lineWidth: anno.setLineWidth(inspector?.lineWidth ?? 0) break case .style: anno.setBorderStyle(CPDFBorderStyle(rawValue: inspector?.style ?? 0) ?? .solid) break case .dashPattern: anno.setDashPattern(inspector?.dashPattern ?? []) break case .startLineStyle: if anno.isLine() { (anno as? CPDFLineAnnotation)?.startLineStyle = CPDFLineStyle(rawValue: inspector?.startLineStyle ?? 0) ?? .none } break case .endLineStyle: if anno.isLine() { (anno as? CPDFLineAnnotation)?.endLineStyle = CPDFLineStyle(rawValue: inspector?.endLineStyle ?? 0) ?? .none } break case .no: break } // mwcFlags.updatingLine = 0; // in case one property changes another, e.g. when adding a dashPattern the borderStyle can change } } // [self updateLineInspector]; } // MARK: - // MARK: 显示窗口 internal func showCompressWindow(url: URL? = nil) { // if let wc = self.compressWIndowControllerNew, let _ = wc.window?.isSheet { // KMPrint("压缩窗口已显示") // return // } self.compressWIndowControllerNew = KMCompressWIndowControllerNew(windowNibName: "KMCompressWIndowControllerNew") self.view.window?.beginSheet(self.compressWIndowControllerNew!.window!) self.compressWIndowControllerNew?.password = self.listView?.document?.password ?? "" // if let _url = url { // windowController.oriDocumentUrl = self.listView.document.documentURL // windowController.documentURL = _url // } else { self.compressWIndowControllerNew?.documentURL = self.listView.document.documentURL // } self.compressWIndowControllerNew?.itemClick = { [unowned self] in self.view.window?.endSheet((self.compressWIndowControllerNew?.window)!) self.toolbarController.cancelSelected(KMToolbarToolCompressItemIdentifier) } self.compressWIndowControllerNew?.batchAction = { [unowned self] view, filePaths in self.view.window?.endSheet((self.compressWIndowControllerNew?.window)!) self.toolbarController.cancelSelected(KMToolbarToolCompressItemIdentifier) let batchWindowController = KMBatchOperateWindowController.sharedWindowController // batchWindowController.window?.makeKeyAndOrderFront("") let batchOperateFile = KMBatchOperateFile(filePath: filePaths.first!.path, type: .Compress) batchWindowController.switchToOperateType(KMBatchOperationType.Compress, files: [batchOperateFile]) batchWindowController.window?.makeKeyAndOrderFront("") } self.compressWIndowControllerNew?.resultCallback = { [unowned self] result, openDocument, fileURL, error in self.view.window?.endSheet((self.compressWIndowControllerNew?.window)!) if (result) { self.toolbarController.cancelSelected(KMToolbarToolCompressItemIdentifier) if (openDocument) { NSDocumentController.shared.openDocument(withContentsOf: fileURL, display: true) { document, result, error in } } else { NSWorkspace.shared.activateFileViewerSelecting([fileURL]) } } else { let alert = NSAlert() alert.messageText = NSLocalizedString("Compress Faild", comment: "") alert.runModal() } } } internal func showConvertWindow(type: KMToolbarType, documentUrl: URL? = nil, identifier: String?) { if let wc = self.currentWindowController as? KMConvertBaseWindowController, let _ = wc.window?.isSheet { KMPrint("转档窗口已显示") return } var convertT: KMConvertType = .Word var windowController: KMConvertBaseWindowController? if (type == .word) { /// Word convertT = .Word } else if (type == .excel) { convertT = .Excel } else if (type == .ppt || type == .rtf || type == .html || type == .conversion_text) { if (type == .ppt) { convertT = .PPT } else if (type == .rtf) { convertT = .RTF } else if (type == .html) { convertT = .HTML } else if (type == .conversion_text) { convertT = .Text } } else if (type == .csv) { convertT = .CSV } else if (type == .conversion_image) { windowController = KMConvertImageWindowController() convertT = .JPEG } else if type == .json { convertT = .Json } windowController?.subscribeWaterMarkType = type.toSubscribeWaterMarkType() var url: URL? if (documentUrl != nil) { url = documentUrl windowController?.oriDocumentUrl = self.listView.document.documentURL } else { url = self.listView.document.documentURL } self.showAllConvertWindow(convertT: convertT) } //MARK: 转档 - func showAllConvertWindow(convertT: KMConvertType) { self.ConvertTrackEvent(type: convertT) let convertWC = KMConvertWindowController(documemtV: self.document!, currentPage: self.listView.currentPage(), convertT: convertT) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [self] in var type: KMConvertWithPDFType = .WordAdvance switch convertT { case .Word: break case .Excel: type = .Excel case .PPT: type = .PowerPoint case .RTF: type = .RTF case .CSV: type = .CSV case .HTML: type = .HTML case .Text: type = .Text case .JPEG: type = .JPEG case .PNG: type = .PNG case .GIF: type = .GIF case .JPG: type = .JPG case .TIFF: type = .TIFF case .TGA: type = .TGA case .BMP: type = .BMP case .JP2: type = .JPEG2000 case .AdvancedWord: break case .Json: type = .Json break default: break } // let document = self.document let batchWindowController = KMBatchOperateWindowController.sharedWindowController var needShowHint = false if KMConvertOperationQueue.sharedQueue.operations.count > 0 { needShowHint = true } else { var needContinue = false if KMBatchOperateManager.defaultManager.files?.count ?? 0 > 0 { let arr: [String] = converFilesToPath(files: KMBatchOperateManager.defaultManager.files!) let ss = self.document?.documentURL.path if arr.contains(ss!) { needContinue = false }else { needContinue = true } }else { needContinue = true } if needContinue { let ss = self.document?.documentURL.path let file = KMBatchOperateFile(filePath: ss!, type: .Convert) file.password = document?.password ?? "" KMBatchOperateManager.defaultManager.files?.append(file) } batchWindowController.switchToOperateType(.Convert, files: KMBatchOperateManager.defaultManager.files!) batchWindowController.switchToConvertType(convertType: type) } batchWindowController.window?.makeKeyAndOrderFront(nil) if needShowHint { batchWindowController.showIsConvertingHint() } else { } } } self.km_beginSheet(windowC: convertWC) } func ConvertTrackEvent(type: KMConvertType) { var eventStr: String = "Btn_SubTbr_Converter_ToWord" switch type { case .Word: eventStr = "Btn_SubTbr_Converter_ToWord" break case .Excel: eventStr = "Btn_SubTbr_Converter_ToExcel" case .PPT: eventStr = "Btn_SubTbr_Converter_ToPPT" case .RTF: eventStr = "Btn_SubTbr_Converter_ToRTF" case .CSV: eventStr = "Btn_SubTbr_Converter_ToCSV" case .HTML: eventStr = "Btn_SubTbr_Converter_ToHTML" case .Text: eventStr = "Btn_SubTbr_Converter_ToText" case .JPEG: eventStr = "Btn_SubTbr_Converter_ToImage" case .PNG: eventStr = "Btn_SubTbr_Converter_ToImage" case .GIF: eventStr = "Btn_SubTbr_Converter_ToImage" case .JPG: eventStr = "Btn_SubTbr_Converter_ToImage" case .TIFF: eventStr = "Btn_SubTbr_Converter_ToImage" case .TGA: eventStr = "Btn_SubTbr_Converter_ToImage" case .BMP: eventStr = "Btn_SubTbr_Converter_ToImage" case .JP2: eventStr = "Btn_SubTbr_Converter_ToImage" case .AdvancedWord: eventStr = "Btn_SubTbr_Converter_ToWord" break default: break } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Converter", withProperties: ["SubTbr_Btn": eventStr]) } //MARK: 转档 - OCR func showOCRWindow() { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared let type = self.toolbarController.toolbarType ?? .None if type == .Conversion { winC.kEventName = "Reading_Convert_OCR_BuyNow" } else { winC.kEventName = "Reading_OCR_BuyNow" } KMMemberInfo.shared.advancedFunctionUsage() return } let com = KMOCRPDFWindowController(cpdfDocument: self.listView.document!, pwd: self.listView.document?.password ?? "") com.currentIndexPage = self.listView.currentPageIndex self.km_beginSheet(windowC: com) } //MARK: 导出图片 func extractImageAction(num: Int) { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_ExtractImage_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } if !(self.listView.document.allowsPrinting || self.listView.document.allowsCopying) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } let document = self.listView.document var fileURL = document?.documentURL if num == 1 { let pageCount = document?.pageCount ?? 0 let indeSet = NSMutableIndexSet() indeSet.add(in: NSRange(location: 0, length: Int(pageCount))) if indeSet.count == 0 { return } let lastPathName = fileURL?.deletingPathExtension().lastPathComponent ?? "" let tFileName = (String(format: "%@_Extract Images", lastPathName)) let outputSavePanel = NSSavePanel() outputSavePanel.title = NSLocalizedString("Save as PDF", comment: "") outputSavePanel.allowsOtherFileTypes = true outputSavePanel.isExtensionHidden = true outputSavePanel.canCreateDirectories = true outputSavePanel.nameFieldStringValue = tFileName outputSavePanel.beginSheetModal(for: self.view.window!, completionHandler: { (result) in if result == NSApplication.ModalResponse.OK { DispatchQueue.main.async { self.beginProgressSheet(withMessage: NSLocalizedString("Extracting all pictures...", comment: "") + "...", maxValue: 0) let tDestFile = outputSavePanel.url!.path let uniquePath = KMExtractImageWindowController.createDestFolder(path: tDestFile, isUnique: false) let pdfconverter = PDFConvertObject() pdfconverter.extractResourcesFromPDF(at: fileURL?.path ?? "", pdfPassword: document?.password, selectIndexSet: indeSet as IndexSet, destDocPath: uniquePath, moreOptions: nil) self.dismissProgressSheet() let fileManager = FileManager.default if fileManager.fileExists(atPath: tDestFile) { let workspace = NSWorkspace.shared let url = URL(fileURLWithPath: tDestFile) workspace.activateFileViewerSelecting([url]) } } } }) return } if fileURL != nil { self.myDocument?.save(nil) } else { let myDocument = self.myDocument let str = String(format: "%@.pdf", myDocument?.displayName ?? "") let writeSuccess = document!.write(to: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!)) if writeSuccess { var documentTemp = CPDFDocument(url: URL(fileURLWithPath: (kTempSavePath?.stringByAppendingPathComponent(str))!)) fileURL = document?.documentURL } else { NSSound.beep() return } } extract = KMExtractImageWindowController(windowNibName: "KMExtractImageWindowController") extract?.docPath = fileURL?.path ?? "" extract?.password = document?.password ?? "" extract?.currentPage = self.listView.currentPageIndex // extract.beginSheetModal(for: NSApp.mainWindow!, completionHandler: nil) self.km_beginSheet(windowC: extract!) extract?.selectCurrentPageBtn() // self.showCreateStamp() // self.showAddSignature() } //MARK: 创建文字图章示例实际上不会在这里使用 func showCreateStamp() { let stampCreaterWindowController = KMStampCreaterWindowController() stampCreaterWindowController.window?.backgroundColor = .clear self.km_beginSheet(windowC: stampCreaterWindowController) stampCreaterWindowController.beginSheetModal(for: self.view.window) { [weak self] result in if result == 1 { } } } //MARK: 添加签名示例实际上不会在这里使用 func showAddSignature() { let signatureWindowController = KMSignatureWindowController(windowNibName: "KMSignatureWindowController") // signatureWindowController.window?.backgroundColor = .clear // signatureWindowController.beginSheetModal(for: self.view.window) { signature in // // } self.view.window?.beginSheet(signatureWindowController.window!, completionHandler: { returnCode in }) } func beginProgressSheet(withMessage message: String, maxValue: UInt) { // if progressController == nil { // progressController = SKProgressController(windowNibName: "ProgressSheet") // } let progress = SKProgressController() progress.window?.backgroundColor = NSColor.km_init(hex: "#36383B") progress.window?.contentView?.wantsLayer = true progress.window?.contentView?.layer?.backgroundColor = NSColor.km_init(hex: "#36383B").cgColor progress.progressField.textColor = NSColor.white progress.message = NSLocalizedString("Converting...", comment: "") progressC = progress progressC?.message = message if maxValue > 0 { progressC?.indeterminate = false progressC?.maxValue = Double(maxValue) progressC?.progressBar.doubleValue = 0.3 } else { progressC?.indeterminate = true } self.view.km_beginSheet(windowC: progressC!) } func dismissProgressSheet() { progressC?.stopAnimation() self.view.km_endSheet() progressC = nil } func converFilesToPath(files: Array) -> [String] { let newArr = NSMutableArray() for item in files { newArr.add(item.filePath) } return newArr as! [String] } internal func showPrintWindow(pageRange: KMPrintPageRange = KMPrintPageRange(type: .allPage, selectPages: [])) { self.saveDocument() if (self.listView.document != nil && !self.listView.document.allowsPrinting) { // 有打印限制 KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: self.listView.document.documentURL) { [weak self] result ,password in if (result == .cancel) { return } // 解除权限 self?.listView.document.unlock(withPassword: password) // 隐藏提示 self?.hiddenSecureLimitTip() // 去打印 KMPrintWindowController.openDocument(inputDocument: self?.listView?.document, inputPageRange: pageRange) } return } KMPrintWindowController.openDocument(inputDocument: self.listView?.document, inputPageRange: pageRange) } // MARK: - 图片注释 @IBAction func imageAnnotation(_ sender: Any) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Image"]) changeAnnotationMode(sender) guard KMMemberInfo.shared.isMemberAllFunction else { KMMemberInfo.shared.advancedFunctionUsage() return } let accessoryCtr = KMImageAccessoryController() let openPanel = NSOpenPanel() openPanel.allowedFileTypes = KMImageAccessoryController.supportedImageTypes() openPanel.allowsMultipleSelection = false openPanel.accessoryView = accessoryCtr.view openPanel.canSelectHiddenExtension = true openPanel.beginSheetModal(for: NSApp.mainWindow!) { [self] (result) in if result == .OK { guard let url = openPanel.url else { return } let filePath = url.path if filePath.pathExtension.lowercased() == "pdf" { if let pdf = PDFDocument(url: url), pdf.isEncrypted { NSSound.beep() return } } guard let image = NSImage(contentsOfFile: url.path) else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), url.lastPathComponent) alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "") alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in if response == .alertFirstButtonReturn { // Handle cancel button clicked } } return } let isDamageImage: Bool = self.isDamageImage(image, imagePath: url.path) if isDamageImage { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: NSLocalizedString("The file \"%@\" could not be opened.", comment: ""), url.lastPathComponent) alert.informativeText = NSLocalizedString("It may be damaged or use a file format that PDF Reader Pro doesn’t recognize.", comment: "") alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.beginSheetModal(for: NSApp.mainWindow!) { (response) in if response == .alertFirstButtonReturn { // Handle cancel button clicked } } return } let isRemoveBGColor = accessoryCtr.selectedButton.state == .on listView.addAnnotation(with: image, isRemoveBGColor: isRemoveBGColor) if (self.listView.activeAnnotation != nil) && (self.listView.activeAnnotation.type == "Image") { self.rightSideViewController.reloadDataWithPDFView(pdfView: self.listView, isShow: true) } } } } @IBAction func tableAnnotation(_ sender: Any) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Table"]) changeAnnotationMode(sender) guard KMMemberInfo.shared.isMemberAllFunction else { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_Table_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } listView.addAnnotationWithTable() openRightPane() } func isDamageImage(_ image: NSImage, imagePath path: String) -> Bool { let addImageAnnotation = (NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last! as NSString).appendingPathComponent(Bundle.main.bundleIdentifier!) if !FileManager.default.fileExists(atPath: addImageAnnotation) { try? FileManager.default.createDirectory(atPath: addImageAnnotation, withIntermediateDirectories: false, attributes: nil) } if let data = image.tiffRepresentation, let imageRep = NSBitmapImageRep(data: data) { imageRep.size = image.size var imageData: Data? if path.lowercased() == "png" { imageData = imageRep.representation(using: .png, properties: [:]) } else { imageData = imageRep.representation(using: .jpeg, properties: [:]) } if let imageData = imageData { let rPath = (addImageAnnotation as NSString).appendingPathComponent((self.tagString() as NSString).appendingPathExtension("png")!) if !((try? imageData.write(to: URL(fileURLWithPath: rPath), options: .atomicWrite)) != nil) { return true } else { return false } } } return false } func tagString() -> String { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "yyMMddHHmmss" return "\(dateFormatter.string(from: Date()))\(Int.random(in: 0..<10000))" } // MARK: - Split View @IBAction func secondaryViewOpenFile(_ sender: NSButton) -> Void { } @objc func removeSecondaryPdfContentView(_ sender: Notification?) { if let _ = sender { NotificationCenter.default.removeObserver(self, name: KMSplitView.animationDidEndNotification, object: self.newPDFSplitView) } self.secondaryPdfContentView?.removeFromSuperview() self.newPDFSplitView.adjustSubviews() } func singlePageScreen(isSinglePage: Bool, doublePagesScreen isHorizontal: Bool) -> Void { if !isSinglePage && isHorizontal { self.openSecondaryPdfView?.changeBenefit(ofContrastLabelWidth: 208) } if (!isSinglePage && !isHorizontal) { self.openSecondaryPdfView?.changeBenefit(ofContrastLabelWidth: 300) } self.displaySinglePageScreen(isSinglePage: isSinglePage, doublePageScreen: isHorizontal) } func displaySinglePageScreen(isSinglePage: Bool, doublePageScreen isHorizontal: Bool) -> Void { if isSinglePage { if self.newPDFSplitView.animating { return } if self.secondaryPdfContentView?.window != nil { self.lastSplitPDFHeight = self.lastSplitPDFHeightFloat(self.secondaryPdfContentView?.frame ?? .zero) self.newPDFSplitView.setPosition(self.newPDFSplitView.maxPossiblePositionOfDivider(at: 0), ofDividerAt: 0, animate: true) if self.newPDFSplitView.animating { NotificationCenter.default.addObserver(self, selector: #selector(removeSecondaryPdfContentView), name: KMSplitView.animationDidEndNotification, object: self.newPDFSplitView) } else { self.removeSecondaryPdfContentView(nil) } } self.view.window?.recalculateKeyViewLoop() if self.interactionMode == .legacyFullScreen { self.view.window?.makeFirstResponder(self.listView) } } else { if self.newPDFSplitView.animating { return } self.newPDFSplitView.dividerStyle = .paneSplitter self.newPDFSplitView.isVertical = isHorizontal if self.secondaryPdfView?.window == nil { let frame = self.newPDFSplitView.bounds if (self.lastSplitPDFHeight <= 0.0) { var DEFAULT_SPLIT_PDF_FACTOR: Float = 0.3 self.lastSplitPDFHeight = floorf(DEFAULT_SPLIT_PDF_FACTOR * self.lastSplitPDFHeightFloat(frame)) } var position = self.lastSplitPDFHeightFloat(frame)-self.lastSplitPDFHeight-Float(self.newPDFSplitView.dividerThickness) var point: NSPoint = .zero var page: CPDFPage? self.newPDFSplitView.setPosition(position.cgFloat, ofDividerAt: 0, animate: true) if (self.secondaryPdfContentView == nil) { // secondaryPdfContentView = [[SKGradientView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200.0, 20.0)]; self.secondaryPdfContentView = NSView(frame: NSMakeRect(0, 0, 200, 20)) self.secondaryPdfView = KMSecondaryPDFView(frame: self.secondaryPdfContentView?.bounds ?? .zero) self.secondaryPdfView?.autoresizingMask = [.width, .height] // self.secondaryPdfContentView?.isHidden = true self.secondaryPdfContentView?.addSubview(self.secondaryPdfView!) self.newPDFSplitView.addSubview(self.secondaryPdfContentView!) // self.newPDFSplitView.addArrangedSubview(self.secondaryPdfContentView!) // // Because of a PDFView bug, display properties can not be changed before it is placed in a window self.secondaryPdfView?.synchronizedPDFView = self.listView self.secondaryPdfView?.backgroundColor = self.listView.backgroundColor // [secondaryPdfView applyDefaultPageBackgroundColor]; self.secondaryPdfView?.displaysPageBreaks = false self.secondaryPdfView?.setShouldAntiAlias(KMPreference.shared.antiAliasText) self.secondaryPdfView?.applyDefaultInterpolationQuality() self.secondaryPdfView?.setGreekingThreshold(KMPreference.shared.greekThreshold.cgFloat) self.secondaryPdfView?.setSynchronizeZoom(true) // // [secondaryPdfView setDocument:[pdfView document]]; point = NSMakePoint(NSMinX(frame), NSMaxY(frame) - position.cgFloat - self.newPDFSplitView.dividerThickness) page = self.listView.page(for: point, nearest: true) // let controlView = self.secondaryPdfView?.controlView var color = NSColor(calibratedWhite: 0.97, alpha: 1.0) if KMAppearance.isDarkMode() { color = KMAppearance.Layout.l0Color() } // [(SKGradientView *)secondaryPdfContentView setGradient:[[[NSGradient alloc] initWithStartingColor:color endingColor:color] autorelease]]; // [(SKGradientView *)secondaryPdfContentView setAlternateGradient:nil]; var pdfRect: NSRect = .zero var controlRect: NSRect = .zero NSDivideRect(self.secondaryPdfContentView?.bounds ?? .zero, &controlRect, &pdfRect, NSHeight(controlView?.frame ?? .zero), .minY) controlRect.size.width = NSWidth(controlView?.frame ?? .zero) controlView?.frame = controlRect controlView?.autoresizingMask = [.maxXMargin, .maxYMargin, .width] // [(SKGradientView *)secondaryPdfContentView setMinSize:controlRect.size]; self.secondaryPdfView?.frame = pdfRect self.secondaryPdfContentView?.addSubview(controlView!) self.openSecondaryPdfView = KMSecondaryViewController() self.openSecondaryPdfView?.view.frame = self.secondaryPdfContentView?.frame ?? .zero self.secondaryPdfContentView?.addSubview(self.openSecondaryPdfView!.view) self.openSecondaryPdfView?.secondaryView.receivedFileUrlBlock = { [weak self] fileUrl in if let docUrl = fileUrl { _ = self?.displaySecondaryPDFView(withUrl: docUrl) self?.openSecondaryPdfView?.view.removeFromSuperview() self?.openSecondaryPdfView = nil } } self.openSecondaryPdfView?.delegate = self if (!isHorizontal) { self.openSecondaryPdfView?.changeBenefit(ofContrastLabelWidth: 300) } } else { self.secondaryPdfContentView?.isHidden = true self.newPDFSplitView.addSubview(self.secondaryPdfContentView!) } // self.newPDFSplitView.setPosition(self.secondaryPdfContentView?.bounds.size.width ?? 120, ofDividerAt: 1, animate: true) if (page != nil) { self.secondaryPdfView?.go(toPageIndex: Int(page!.pageIndex()), animated: false) // point = [secondaryPdfView convertPoint:[secondaryPdfView convertPoint:[pdfView convertPoint:point toPage:page] fromPage:page] toView:[secondaryPdfView documentView]]; let tmpP = self.listView.convert(point, to: page) let conP = self.secondaryPdfView?.convert(tmpP, from: page) ?? .zero point = self.secondaryPdfView?.convert(conP, to: self.secondaryPdfView?.documentView()) ?? .zero if let docView = self.secondaryPdfView?.documentView(), docView.contentView.isFlipped == false { point.y -= docView.isFlipped ? -NSHeight(docView.visibleRect) : NSHeight(docView.visibleRect) } self.secondaryPdfView?.documentView()?.scroll(point) self.secondaryPdfView?.layoutDocumentView() } } self.view.window?.recalculateKeyViewLoop() if self.interactionMode == .legacyFullScreen { self.view.window?.makeFirstResponder(self.listView) } if self.secondaryPdfView?.document == nil { self.openSecondaryPdfView?.viewHighlyAdaptive() } } } func lastSplitPDFHeightFloat(_ rect: NSRect) -> Float { if (self.newPDFSplitView.isVertical) { return Float(NSWidth(rect)) } else { return Float(NSHeight(rect)) } } func displaySecondaryPDFView(withUrl url: URL) -> Bool { let document = CPDFDocument.init(url: url) if document != nil { self.secondaryPdfView?.document = nil self.secondaryPdfView?.document = document self.rightSideViewController.annotationProperties.openPropertiesType = .pageDisplay return true } else { return false } } func updateNextAndPreViousButtonState() { let item = self.toolbarController.mainToolBarView?.toolbarItemFindItemIdentifiers(value: KMDocumentPreviousPageToolbarItemIdentifier) let view = item?.customizeView as? KMToolbarPreviousNextItemView if let can = self.listView?.canGoToPreviousPage() { view?.previousButton.isEnabled = can } else { view?.previousButton.isEnabled = false } if let can = self.listView?.canGoToNextPage() { view?.nextButton.isEnabled = can } else { view?.nextButton.isEnabled = false } } func updateBackAndForwardButtonState() { let toItem = self.toolbarController.mainToolBarView?.toolbarItemFindItemIdentifiers(value: KMDocumentPreviousPageToolbarItemIdentifier) if self.listView.km_canGoForward() { toItem?.unEnabled = false } else { toItem?.unEnabled = true } } } // MARK: - // MARK: - KMSecondaryViewControllerDelegate extension KMMainViewController: KMSecondaryViewControllerDelegate { func receivedFileUrl(_ url: URL!) { let state = self.displaySecondaryPDFView(withUrl: url) if !state { 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() return } else { self.openSecondaryPdfView?.view.removeFromSuperview() self.openSecondaryPdfView = nil } } func controllerDidClose(_ controller: KMSecondaryViewController!) { self.singlePageScreen(isSinglePage: true, doublePagesScreen: false) } } // MARK: - // MARK: - KMToolbarViewControllerDelegate extension KMMainViewController : KMToolbarViewControllerDelegate { func changeModelAction(mode: CToolMode) { self.listView.toolMode = mode if mode == .editPDFToolMode { self.childToolbarController.updateType(newType: .editPDF) } } func toolbarViewController(_ viewController:KMToolbarViewController, zoomModel selectedTag:Int) { switch selectedTag { case 2: if self.listView.scaleFactor != 1.0 { self.listView.scaleFactor = 1.0 self.listView.autoScales = false } break case 1: let pageHeight = self.listView.currentPage()!.size.height let pdfviewHeight = self.listView.bounds.size.height self.listView.scaleFactor = pdfviewHeight/pageHeight self.listView.autoScales = false break case 0: // self.listView.autoScales = !self.listView.autoScales self.listView.autoScales = true break case 3: self.listView.scaleFactor = 0.1 break case 4: self.listView.scaleFactor = 0.25 break case 5: self.listView.scaleFactor = 0.5 break case 6: self.listView.scaleFactor = 0.75 break case 7: self.listView.scaleFactor = 1.0 break case 8: self.listView.scaleFactor = 1.5 break case 9: self.listView.scaleFactor = 2.0 break case 10: self.listView.scaleFactor = 4.0 break case 11: self.listView.scaleFactor = 8.0 break case 12: self.listView.scaleFactor = 16.0 break case 13: self.listView.scaleFactor = 32.0 break case 14: self.listView.scaleFactor = 64.0 break case 15: self.listView.scaleFactor = 100.0 break default: break } viewController.zoomTextField.stringValue = "\(Int(self.listView.scaleFactor*100))%" if self.digitalSignController?.pdfView != nil { self.digitalSignController?.pdfView.scaleFactor = self.listView.scaleFactor } if self.redactController?.redactPdfView != nil { self.redactController?.redactPdfView.scaleFactor = self.listView.scaleFactor } } func toolbarViewController(_ viewController: KMToolbarViewController, zoomSting: String) { var scale = CGFloat((NSString(string: zoomSting)).floatValue / 100.0) if scale > 100 { scale = 100 } if (scale <= 0.101) { self.listView.scaleFactor = self.listView.minScaleFactor() } else { self.listView.scaleFactor = scale } if self.digitalSignController?.pdfView != nil { self.digitalSignController?.pdfView.scaleFactor = self.listView.scaleFactor } if self.redactController?.redactPdfView != nil { self.redactController?.redactPdfView.scaleFactor = self.listView.scaleFactor } viewController.zoomTextField.stringValue = "\(Int(self.listView.scaleFactor*100))%" } func changePDFViewZoomInAction() { let zoomSting = self.toolbarController.mainToolBarView?.zoomTextField.stringValue ?? "10" var scale = CGFloat((NSString(string: zoomSting)).floatValue / 100.0) switch scale { case 0...0.25: scale += 0.25 case 0.25...3: scale += 0.25 case 3.1...10: scale += 0.4 case 10.1...100: scale += 1 default: scale += 1 } self.listView.scaleFactor = scale // nearbyint self.toolbarController.mainToolBarView?.zoomTextField.stringValue = "\(Int(self.listView.scaleFactor*100))%" // self.listView.zoomIn(nil) if self.digitalSignController?.pdfView != nil { self.digitalSignController?.pdfView.scaleFactor = scale } if self.redactController?.redactPdfView != nil { self.redactController?.redactPdfView.scaleFactor = scale } } func changePDFViewZoomOutAction() { let zoomSting = self.toolbarController.mainToolBarView?.zoomTextField.stringValue ?? "10" var scale = CGFloat((NSString(string: zoomSting)).floatValue / 100.0) switch scale { case 0...0.25: scale = 0 case 0.25...3: scale -= 0.25 case 3.1...10: scale -= 0.4 case 10.1...100: scale -= 1 default: scale -= 1 } self.listView.scaleFactor = scale // nearbyint self.toolbarController.mainToolBarView?.zoomTextField.stringValue = "\(Int(self.listView.scaleFactor*100))%" // self.listView.zoomOut(nil) if self.digitalSignController?.pdfView != nil { self.digitalSignController?.pdfView.scaleFactor = scale } if self.redactController?.redactPdfView != nil { self.redactController?.redactPdfView.scaleFactor = scale } self.savePageNumberIfNeed() } func changePDFViewGotoNextPageAction() { self.listView.km_goBack(nil) if (self.listView.canGoToNextPage()) { self.listView.goToNextPage(nil) } self.updateNextAndPreViousButtonState() } func changePDFViewGoToPreviousPageAction() { if (self.listView.canGoToPreviousPage()) { self.listView.goToPreviousPage(nil) } self.updateNextAndPreViousButtonState() } func changePDFViewGotoBackAction() { self.listView.km_goBack(nil) self.updateBackAndForwardButtonState() } func changePDFViewGoToForwardAction() { self.listView.km_goForward(nil) self.updateBackAndForwardButtonState() } func aiTranslationPDFFileAction() { #if VERSION_DMG #else if !KMLightMemberManager.manager.isLogin() && NSApp.mainWindow != nil { KMLoginWindowController.show(window: NSApp.mainWindow!) return } #endif self.trackEvent_aiTranslate() self._aiTranslationPDFFileAction() } private func _aiTranslationPDFFileAction() { let isExceedsLimit = self.isPDFPageCountExceedsLimit(filePath: (self.document?.documentURL.path)!) if KMTools.isFileGreaterThan10MB(atPath: (self.document?.documentURL.path)!) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("The uploaded file size cannot exceed 10MB", comment: "") alert.runModal() return } else if isExceedsLimit { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Documents cannot exceed 30 pages", comment: "") alert.runModal() return } let alert = NSAlert() alert.messageText = NSLocalizedString("Processing times may be longer for larger documents. Thank you for your patience.", comment: "") alert.addButton(withTitle: NSLocalizedString("Continue", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.beginSheetModal(for: view.window!) { [unowned self] result in if (result == .alertFirstButtonReturn) { self.aiTranslationConfirWC = KMAITranslationConfirmWindowController.init(windowNibName: NSNib.Name("KMAITranslationConfirmWindowController")) self.aiTranslationConfirWC!.filePath = (self.document?.documentURL.path)! self.view.window?.beginSheet(self.aiTranslationConfirWC!.window!) } else if result == .alertSecondButtonReturn { return } } } func toolbarViewController(_ viewController: KMToolbarViewController, shareAction toolbarItem: KMToolbarItemView) { self.trackEvent_share() } func toolbarViewController(_ viewController: KMToolbarViewController, shareDocument item: NSMenuItem) { self.shareDocument(sender: viewController) } func toolbarViewController(_ viewController: KMToolbarViewController, shareFlatten item: NSMenuItem) { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_Flatten_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } self.shareFlatten(sender: viewController) } func toolbarViewController(_ viewController: KMToolbarViewController, shareOriginalPDF item: NSMenuItem) { self.shareOriginalPDF(sender: viewController) } func toolbarViewController(_ viewController: KMToolbarViewController, scanOCRModel selectedTag: Int) { if(0 == selectedTag) { } else { } } func mainToolDidClicked(_ toolController: KMToolbarController, _ beforeType: KMToolbarViewType, _ type: KMToolbarViewType, _ item: KMToolbarItemView , _ pages: [Int]) { if beforeType == .editPDF { self.editPDFHanddler.enterEditPDF() } if(type != .Page) { if (hasEnterPageEdit()) { self.exitPageEdit() } } if type != .redact { if self.hasEnterRedact() { self.exitRedact() } } if item.itemIdentifier != KMDocumentDigitalSignToolbarItemIdentifier { if self.hasShowDigitalSign() { self.exitDigitalSign() } } if item.itemIdentifier != KMDocumentViewDisplayToolbarItemIdentifier { self.toolbarController.findItem(KMDocumentViewDisplayToolbarItemIdentifier)?.isSelected = false } if(type != .Form) { self.removeFromAlertView() } if (type == .Page) { if (hasEnterPageEdit()) { self.exitPageEdit() } else { self.enterPageEdit(pages) } } else if type == .editPDF { self.enterEditPDF() } else if type == .Annatiton { self.rightSideViewController.subViewType = .AnnotationProperts } else if type == .redact { if self.needSaveDocument() { self.saveDocumentWithProgressAlert { [unowned self] params in self.enterRedact() } return } let isEdited = self.listView.isEdited() let isPDFTextImageEdited = self.model.isPDFTextImageEdited if isEdited || isPDFTextImageEdited { self.commitEditingIfNeed() // DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { self.enterRedact() // } } else { self.enterRedact() } } else if type == .Tool { if KMGuideInfoWindowController.availableShow(.pdfCompareGuide) { self.loadOpenFileFunctionGuide(.pdfCompareGuide) } else if KMGuideInfoWindowController.availableShow(.measureGuide) { self.loadOpenFileFunctionGuide(.measureGuide) } } else if type == . Conversion { self.loadOpenFileFunctionGuide(.convertGuide) }else if type == .Form { self.showFormAlertView() }else if type == .Select { self.rightSideViewController.isHidden = true self.closeRightPane() } } func clickChildTool(type: KMToolbarType, index: Int) { if (type == .secure) { if (index == 1) { self.trackEvent_setPassword() } else if (index == 2) { self.trackEvent_removePassword() } } else { self.trackEvent(toolBarType: type) } Task { @MainActor in if (type == .compress) { /// 压缩 if !self.documentAllowsEdit() { return } if (self.needSaveDocument()) { self.saveDocumentWithProgressAlert { [unowned self] params in self.showCompressWindow() } return } self.showCompressWindow() return } if ((KMToolbarType.word.rawValue ... KMToolbarType.json.rawValue).contains(type.rawValue)) { /// 转档 if type == .conversion_imageToPDF { Task { let _ = await NSApplication.ShowImageToPDFWindow(urls: []) } return } var identifier: String? if (type == .word) { /// Word identifier = KMToolbarConversionWordItemIdentifier } else if (type == .excel) { identifier = KMToolbarConversionExcelItemIdentifier } else if (type == .ppt) { identifier = KMToolbarConversionPPTItemIdentifier } else if (type == .rtf) { identifier = KMToolbarConversionRTFItemIdentifier } else if (type == .html) { identifier = KMToolbarConversionHTMLItemIdentifier } else if (type == .conversion_text) { identifier = KMToolbarConversionTextItemIdentifier } else if (type == .csv) { identifier = KMToolbarConversionCSVItemIdentifier } else if (type == .conversion_image) { identifier = KMToolbarConversionImageItemIdentifier } if (self.needSaveDocument()) { self.saveDocumentWithProgressAlert { [unowned self] params in self.showConvertWindow(type: type, identifier: identifier) } return } self.showConvertWindow(type: type, identifier: identifier) return } if (type == .merge) { /// 合并 FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Merge"]) if !self.documentAllowsEdit() { return } if (self.needSaveDocument()) { self.saveDocumentWithProgressAlert { [unowned self] params in self.showMergeWindow(self.listView.document.password) } return } self.showMergeWindow(self.listView.document.password) return } if (type == .bates || type == .headerAndFooter) { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared if type == .headerAndFooter { if index == 1 { winC.kEventName = "Reading_AddHeaderFooter_BuyNow" } else if index == 2 { winC.kEventName = "Reading_RemoveHeaderFooter_BuyNow" } } else if type == .bates { if index == 1 { winC.kEventName = "Reading_AddBates_BuyNow" } else if index == 2 { winC.kEventName = "Reading_RemoveBates_BuyNow" } } KMMemberInfo.shared.advancedFunctionUsage() return } if !self.documentAllowsEdit() { return } if (index == 1) { var windowController: KMBaseWindowController = KMBaseWindowController() if (type == .bates) { windowController = KMHeaderFooterWindowController(windowNibName: "KMHeaderFooterWindowController") (windowController as! KMHeaderFooterWindowController).operateCallBack = { [unowned self] controller, headerFooter in let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddBates, filepaths: [fpath]) } windowController.isBates = true } else if (type == .headerAndFooter) { windowController = KMHeaderFooterWindowController(windowNibName: "KMHeaderFooterWindowController") (windowController as! KMHeaderFooterWindowController).operateCallBack = { [unowned self] controller, headerFooter in let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddHeaderFooter, filepaths: [fpath]) } } else if (type == .background) { } else if (type == .watermark) { // controller = KMWatermarkViewController() } windowController.pdfDocument = self.listView.document windowController.cancelAction = { [unowned self] controller in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil } self.currentWindowController = windowController await self.view.window?.beginSheet(windowController.window!) return } if (index == 1) { /// 取消 self.toolbarController.exitWatermarkAdjective() // self.rightSideViewController.view.isHidden = true self.rightSideViewController.isHidden = true self.rightSideViewController.subViewType = .None self.closeRightPane() return } else if index == 3 { let fpath = self.document?.documentURL?.path ?? "" if type == .bates { self.showBatchWindow(type: .AddBates, filepaths: [fpath]) } else { self.showBatchWindow(type: .AddHeaderFooter, filepaths: [fpath]) } } else if index == 4 { let fpath = self.document?.documentURL?.path ?? "" if type == .bates { self.showBatchWindow(type: .RemoveBates, filepaths: [fpath]) } else { self.showBatchWindow(type: .RemoveHeaderFooter, filepaths: [fpath]) } } else if (index == 2) { //// 移除 if type == .headerAndFooter { let savePanelAccessoryViewController = KMSavePanelAccessoryController() let savePanel = NSSavePanel() savePanel.nameFieldStringValue = self.document?.documentURL.deletingPathExtension().lastPathComponent ?? "" savePanel.allowedFileTypes = ["pdf"] savePanel.accessoryView = savePanelAccessoryViewController.view savePanel.beginSheetModal(for: NSWindow.currentWindow()) { [unowned self] result in if result.rawValue == NSApplication.ModalResponse.OK.rawValue { KMHeaderFooterView.saveAsPDFRemoveAllHeaderFooter(document!, password: document?.password, toPath: savePanel.url!.path) { success in if success == 1 && savePanel.url?.path == self.listView?.document?.documentURL.path { self.setDocument = CPDFDocument(url: savePanel.url!) return } if savePanelAccessoryViewController.openAutomaticButton.state == .on { NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePanel.url!.path), display: true) { _, _, _ in } } else { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "") } } } } } else if type == .bates { let savePanelAccessoryViewController = KMSavePanelAccessoryController() let savePanel = NSSavePanel() savePanel.nameFieldStringValue = self.document?.documentURL.deletingPathExtension().lastPathComponent ?? "" savePanel.allowedFileTypes = ["pdf"] savePanel.accessoryView = savePanelAccessoryViewController.view savePanel.beginSheetModal(for: NSWindow.currentWindow()) { [unowned self] result in if result.rawValue == NSApplication.ModalResponse.OK.rawValue { KMHeaderFooterView.saveAsPDFRemoveAllHeaderFooterBates(document!, password: document?.password, toPath: savePanel.url!.path) { success in if success == 1 && savePanel.url?.path == self.listView?.document?.documentURL.path { self.setDocument = CPDFDocument(url: savePanel.url!) return } if savePanelAccessoryViewController.openAutomaticButton.state == .on { NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: savePanel.url!.path), display: true) { _, _, _ in } } else { NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "") } } } } } return } else if (index == 2) { /// 应用 let model = self.rightSideViewController.model if (type == .bates || type == .headerAndFooter) { if (model == nil || (model?.isKind(of: KMHeaderFooterObject.self) == false)) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = "没有找到模型" alert.runModal() return } if ((model as! KMHeaderFooterObject).hasVaild == false) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = "没有找到内容" alert.runModal() return } } KMWatermarkAdjectiveTools.apply(model!, self.listView, self.listView.document.documentURL.path) { result in DispatchQueue.main.async { self.listView.layoutDocumentView() self.listView.setNeedsDisplayForVisiblePages() } if (result) { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = "成功" alert.runModal() } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = "失败" alert.runModal() } } return } else if index == 5 { self.rightSideViewController.isHidden = false self.rightSideViewController.subViewType = KMWatermarkAdjectiveTools.KMToolBarTypeToRightSubViewType(type) self.openRightPane() } } else if (type == .redact) { /// 标记密文 if KMMemberInfo.shared.isMemberAllFunction == false { KMMemberInfo.shared.advancedFunctionUsage() return } if (index == 1) { /// 取消 if (self.model.hasAddRedact) { let alert = NSAlert() alert.messageText = NSLocalizedString("You can save a document with unapplied cipher text and edit it again. If you do not save, all changes will be lost.", comment: "") alert.addButton(withTitle: NSLocalizedString("Don’t Save", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result == .alertFirstButtonReturn) { self.listView.toolMode = .moveToolMode self.toolbarController.exitRedact() } return } self.listView.toolMode = .moveToolMode self.toolbarController.exitRedact() return } if (index == 2) { /// 擦除 self.exeRedactConfirm(.eraserAll) {} return } if (index == 3) { /// 应用 self.exeRedactConfirm(.redactAll) {} return } if (index == 4) { /// 文本&图像 self.listView.toolMode = .redactToolMode return } if (index == 5) { /// 页面 let windowController = KMRedactPageRangeWindowController(windowNibName: "KMRedactBaseWindowController") await self.view.window?.beginSheet(windowController.window!) self.currentWindowController = windowController windowController.itemClick = { [weak self] index, value in if (index == 1) { let topBarView = self?.toolbarController.fetchTopBarView() if (topBarView == nil || topBarView?.isKind(of: KMRedactTopToolBar.self) == false) { return } (topBarView as! KMRedactTopToolBar).selectItem(0) self?.view.window?.endSheet((self?.currentWindowController.window)!) self?.currentWindowController = nil return } let windowController_pageRange = self?.currentWindowController as! KMRedactPageRangeWindowController let pageType = windowController_pageRange.pageType let pageString = windowController_pageRange.pageString if (pageType == 5) { /// 自定义页面 let array = KMPageRangeTools.findSelectPage(pageRangeString: pageString, pageCount: Int((self?.listView.document?.pageCount) ?? 0)) if (array.count == 0) { let alert = NSAlert() alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "") alert.runModal() return } } self!.view.window?.endSheet(self!.currentWindowController.window!) self!.currentWindowController = nil var indexs: IndexSet = [] if (pageType == 1) { /// 当前页面 indexs.insert((self?.listView.currentPageIndex)!) } else { indexs = KMRedactTools.getPageIndexs(pageType-1, string: pageString, Int((self?.listView.document?.pageCount) ?? 0)) } if (indexs.count == 0) { return } for i in indexs { let page: CPDFPage = (self?.listView.document.page(at: UInt(i)))! let redactAnno = CPDFRedactAnnotation(PDFListViewNoteWith: (self?.listView.document)!) redactAnno.bounds = page.bounds self?.listView.add(redactAnno, to: page) } } return } } else if (type == .secure) { /// 安全 if (index == 1) { /// 设置密码 if (!self.listView.document!.allowsCopying || !self.listView.document!.allowsPrinting) { if !self.documentAllowsEdit() { return } // KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: self.listView.document.documentURL) { [weak self] result, password in // if (result == .cancel) { // return // } // // self?.isSaveKeyChain = false // self?.listView.document.unlock(withPassword: password) // self?.hiddenSecureLimitTip() // // self?.showSecureWindow((self?.listView.document.documentURL)!) // } // return } self.showSecureWindow(self.listView.document.documentURL) return } else if index == 2 { if !self.document!.allowsCopying || !self.document!.allowsPrinting { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Warning", comment: "") alert.informativeText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.addButton(withTitle: NSLocalizedString("Remove Security", comment: "")) alert.beginSheetModal(for: NSWindow.currentWindow()) { returnCode in if returnCode == .alertSecondButtonReturn { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [unowned self] in KMBaseWindowController.checkPassword(url: self.document!.documentURL!, type: .owner) { [unowned self] success, resultPassword in if success { self.document?.unlock(withPassword: resultPassword) self.clickChildTool(type: .secure, index: 2) } } } } } } else { let controller = KMRemovePasswordWindowController(windowNibName: "KMRemovePasswordWindowController") controller.pdfDocument = self.document self.currentWindowController = controller controller.batchAction = { [unowned self] controller, files in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil self.toolbarController.cancelSelected(KMToolbarToolCompressItemIdentifier) let baseWindowController = KMBatchOperateBaseWindowController(windowNibName: "KMBatchOperateBaseWindowController") if #available(macOS 10.13, *) { baseWindowController.window?.makeKeyAndOrderFront(nil) } else { baseWindowController.showWindow(nil) } let arr = NSMutableArray() let file = KMBatchOperateFile(filePath: self.listView!.document!.documentURL!.path, type: .RemovePassword) file.password = document?.password ?? "" arr.add(file) // baseWindowController.checkNeedPasswordSwitchToOperateType(operateType: .RemovePassword, files: arr as! [KMBatchOperateFile]) baseWindowController.switchToOperateType(.RemovePassword, files: arr as! [KMBatchOperateFile]) } controller.cancelAction = { [unowned self] controller in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil } controller.doneAction = { [unowned self] controller in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil KMBaseWindowController.checkPassword(url: self.document!.documentURL!, type: .owner, password: self.document?.password ?? "") { [unowned self] success, resultPassword in if success { // let savePanelAccessoryViewController = KMSavePanelAccessoryController() let savePanel = NSSavePanel() savePanel.nameFieldStringValue = self.listView.document.documentURL.deletingPathExtension().lastPathComponent + "_RemovePassword" savePanel.allowedFileTypes = ["pdf"] // savePanel.accessoryView = savePanelAccessoryViewController.view savePanel.beginSheetModal(for: NSApp.mainWindow!) {[unowned self] result in guard result == .OK else { return } /// 删除安全性设置 if (!self.listView.document!.allowsCopying || !self.listView.document!.allowsPrinting) { self.model.isSaveKeyChain = false self.listView.document.unlock(withPassword: resultPassword) } let document = CPDFDocument.init(url: self.listView.document.documentURL) guard let document = document else { return } document.unlock(withPassword: resultPassword) let success = document.writeDecrypt(to: savePanel.url) if success { self.hiddenSecureLimitTip() let tip = KMRemovePasswordResultTipView() tip.result = .success tip.showInView(superView: (self.listView.superview)!) NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!]) } else { self.hiddenSecureLimitTip() let tip = KMRemovePasswordResultTipView() tip.result = .failure tip.showInView(superView: (self.listView.superview)!) } } } } } await NSWindow.currentWindow().beginSheet(controller.window!) } return } } else if type == .comparison { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Compare"]) if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_Compare_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } let controller = KMCompareWindowController(windowNibName: "KMCompareWindowController") self.currentWindowController = controller controller.password = self.document?.password ?? "" controller.filePath = (self.document?.documentURL.path)! controller.cancelAction = { [unowned self] controller in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil } controller.contentComplete = { [unowned self] controller, pdfCompareContent, result, oldDocument, document in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil self.openContentCompareVC(with: pdfCompareContent, results: result, oldDocument: oldDocument, document: document) } controller.coveringComplete = { [unowned self] controller, document in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil self.openCoveringCompareVC(with: document) } if index == 1 { controller.fileType = .content } else { controller.fileType = .coverting } await NSWindow.currentWindow().beginSheet(controller.window!) } else if type == .watermark { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared if index == 1 { winC.kEventName = "Reading_AddWatermark_BuyNow" } else if index == 2 { winC.kEventName = "Reading_RemoveWatermark_BuyNow" } KMMemberInfo.shared.advancedFunctionUsage() return } if !self.documentAllowsEdit() { return } if index == 1 { self.watermarkWindowController = KMWatermarkWindowController(windowNibName: "KMWatermarkWindowController") self.watermarkWindowController!.pdfDocument = self.document self.watermarkWindowController!.cancelAction = { [unowned self] controller in // self.view.window?.endSheet((self.watermarkWindowController!.window)!) self.km_endSheet() } self.watermarkWindowController!.operateCallBack = { [unowned self] controller, watermark, countType in // self.view.window?.endSheet((self.watermarkWindowController!.window)!) self.km_endSheet() let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddWatermark, filepaths: [fpath]) } // NSWindow.currentWindow().beginSheet(controller.window!) // NSWindow.currentWindow().beginSheet(self.watermarkWindowController!.window!, completionHandler: nil) self.km_beginSheet(windowC: self.watermarkWindowController!) } else if index == 2 { let watermarks = self.listView.document.watermarks() if (watermarks == nil || watermarks!.count <= 0) { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Could not find a removable watermark in this document. If you see a watermark, it was not added with PDF Reader Pro and therefore cannot be detected.", comment: "") alert.addButton(withTitle: NSLocalizedString("Confirm", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) alert.runModal() return } let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Are you sure you want to remove the watermark?", comment: "") alert.addButton(withTitle: NSLocalizedString("Delete", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result != .alertFirstButtonReturn) { return } let savePanelAccessoryViewController = KMSavePanelAccessoryController() let savePanel = NSSavePanel() savePanel.nameFieldStringValue = self.listView.document.documentURL.deletingPathExtension().lastPathComponent savePanel.allowedFileTypes = ["pdf"] savePanel.accessoryView = savePanelAccessoryViewController.view savePanel.beginSheetModal(for: NSApp.mainWindow!) { result in guard result == .OK else { return } let oType: KMWatermarkAdjectiveType = KMWatermarkAdjectiveTools.KMWatermarkAdjectiveType(from: type) KMWatermarkAdjectiveTools.delete(oType, self.listView, savePanel.url!.path) { result in DispatchQueue.main.async { self.listView.layoutDocumentView() self.listView.setNeedsDisplayForVisiblePages() } if (result) { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Finish", comment: "") alert.runModal() if savePanel.url?.path == self.listView?.document?.documentURL.path { self.setDocument = CPDFDocument(url: savePanel.url!) return } let needOpen = savePanelAccessoryViewController.needOpen if needOpen { NSDocumentController.shared.km_safe_openDocument(withContentsOf: savePanel.url!, display: true) { document, hasOpen, err in } } else { NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!]) } } else { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("Failed", comment: "") alert.runModal() } } } } else if index == 3 { let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddWatermark, filepaths: [fpath]) } else if index == 4 { let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .RemoveWatermark, filepaths: [fpath]) } else if index == 5 { self.rightSideViewController.isHidden = false self.rightSideViewController.subViewType = KMWatermarkAdjectiveTools.KMToolBarTypeToRightSubViewType(type) self.openRightPane() return } } else if type == .background { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared if index == 1 { winC.kEventName = "Reading_AddBackground_BuyNow" } else if index == 2 { winC.kEventName = "Reading_RemoveBackground_BuyNow" } KMMemberInfo.shared.advancedFunctionUsage() return } if !self.documentAllowsEdit() { return } if index == 1 { let controller = KMBackgroundWindowController(windowNibName: "KMBackgroundWindowController") self.currentWindowController = controller controller.pdfDocument = self.document controller.cancelAction = { [unowned self] controller in self.view.window?.endSheet((self.currentWindowController.window)!) self.currentWindowController = nil } controller.operateCallBack = { [unowned self] controller, background, countType in let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddBackground, filepaths: [fpath]) } await NSWindow.currentWindow().beginSheet(controller.window!) } else if index == 2 { guard let document = self.document else { return } if !document.allowsPrinting || !document.allowsCopying { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } guard let documentURL = document.documentURL else { return } let savePanelAccessoryViewController = KMSavePanelAccessoryController() let savePanel = NSSavePanel() savePanel.nameFieldStringValue = documentURL.deletingPathExtension().lastPathComponent savePanel.allowedFileTypes = ["pdf"] savePanel.accessoryView = savePanelAccessoryViewController.view savePanel.beginSheetModal(for: NSApp.mainWindow!) { result in guard result == .OK else { return } KMAddBackgroundView.saveAsPDFRemoveAllBackground(PDFDocument: document, password: document.password, toPath: savePanel.url!.path, completionHandler: { [unowned self] success in if success == 1 { if savePanel.url?.path == self.listView?.document?.documentURL.path { self.setDocument = CPDFDocument(url: savePanel.url!) return } if savePanelAccessoryViewController.openAutomaticButton.state == .on { NSDocumentController.shared.openDocument(withContentsOf: savePanel.url!, display: true) { _, _, _ in } } else { NSWorkspace.shared.selectFile(savePanel.url!.path, inFileViewerRootedAtPath: "") } } }) } } else if index == 3 { let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .AddBackground, filepaths: [fpath]) } else if index == 4 { let fpath = self.document?.documentURL?.path ?? "" self.showBatchWindow(type: .RemoveBackground, filepaths: [fpath]) } else if index == 5 { self.rightSideViewController.isHidden = false self.rightSideViewController.subViewType = KMWatermarkAdjectiveTools.KMToolBarTypeToRightSubViewType(type) self.openRightPane() return } } else if type == .measure { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_Measure_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } if !self.documentAllowsEdit() { return } self.listView.toolMode = .measureToolMode if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.hideFloatingWindow() } else if perimeterMeasureInfoWindowController?.window?.isVisible == true { perimeterMeasureInfoWindowController?.hideFloatingWindow() } else if areaMeasureInfoWindowController?.window?.isVisible == true { areaMeasureInfoWindowController?.hideFloatingWindow() } if distanceMeasureInfoWindowController == nil { let measureInfo = CPDFDistanceMeasureInfo() distanceMeasureInfoWindowController = CDistanceMeasureInfoWindowController() distanceMeasureInfoWindowController?.measureInfo = measureInfo distanceMeasureInfoWindowController?.delegate = self } if perimeterMeasureInfoWindowController == nil { let measureInfo = CPDFPerimeterMeasureInfo() perimeterMeasureInfoWindowController = CPerimeterMeasureInfoWindowController() perimeterMeasureInfoWindowController?.measureInfo = measureInfo perimeterMeasureInfoWindowController?.delegate = self } if areaMeasureInfoWindowController == nil { let measureInfo = CPDFAreaMeasureInfo() areaMeasureInfoWindowController = CAreaMeasureInfoWindowController() areaMeasureInfoWindowController?.measureInfo = measureInfo areaMeasureInfoWindowController?.delegate = self } if index == 1 { self.listView.annotationType = .line let winW: CGFloat = 300 let rightW: CGFloat = 270 var winFrame = self.view.window?.frame ?? .zero winFrame.origin.x += (winFrame.size.width-winW-rightW) distanceMeasureInfoWindowController?.window?.setFrameOrigin(winFrame.origin) distanceMeasureInfoWindowController?.showWindow(nil) distanceMeasureInfoWindowController?.lengthLabel.stringValue = "" distanceMeasureInfoWindowController?.angleLabel.stringValue = "" distanceMeasureInfoWindowController?.xLabel.stringValue = "" distanceMeasureInfoWindowController?.yLabel.stringValue = "" self.toolbarController.findItem(KMToolbarMeasureItemIdentifier)?.isSelected = true _ = CustomAlertView.alertView(message: "ESC to exit continuous measuring mode.", fromView: self.view, withStyle: .black) self.trackEvent(toolMode: .measureToolMode) } else if index == 2 { self.listView.annotationType = .polyLine let winW: CGFloat = 300 let rightW: CGFloat = 270 var winFrame = self.view.window?.frame ?? .zero winFrame.origin.x += (winFrame.size.width-winW-rightW) perimeterMeasureInfoWindowController?.window?.setFrameOrigin(winFrame.origin) perimeterMeasureInfoWindowController?.showWindow(nil) perimeterMeasureInfoWindowController?.lengthLabel.stringValue = "" perimeterMeasureInfoWindowController?.angleLabel.stringValue = "" self.toolbarController.findItem(KMToolbarMeasureItemIdentifier)?.isSelected = true _ = CustomAlertView.alertView(message: "Double-click to finish drawing. Press ESC to exit continuous measuring mode.", fromView: self.view, withStyle: .black) self.trackEvent(toolMode: .measureToolMode) } else if index == 3 { self.listView.annotationType = .polyGon let winW: CGFloat = 300 let rightW: CGFloat = 270 var winFrame = self.view.window?.frame ?? .zero winFrame.origin.x += (winFrame.size.width-winW-rightW) areaMeasureInfoWindowController?.window?.setFrameOrigin(winFrame.origin) areaMeasureInfoWindowController?.showWindow(nil) areaMeasureInfoWindowController?.areaLabel.stringValue = "" areaMeasureInfoWindowController?.angleLabel.stringValue = "" self.toolbarController.findItem(KMToolbarMeasureItemIdentifier)?.isSelected = true _ = CustomAlertView.alertView(message: "Double-click to finish drawing. Press ESC to exit continuous measuring mode.", fromView: self.view, withStyle: .black) self.trackEvent(toolMode: .measureToolMode) } else if index == 4 { self.listView.annotationType = .square let winW: CGFloat = 300 let rightW: CGFloat = 270 var winFrame = self.view.window?.frame ?? .zero winFrame.origin.x += (winFrame.size.width-winW-rightW) areaMeasureInfoWindowController?.window?.setFrameOrigin(winFrame.origin) areaMeasureInfoWindowController?.showWindow(nil) areaMeasureInfoWindowController?.areaLabel.stringValue = "" areaMeasureInfoWindowController?.angleLabel.stringValue = "" self.toolbarController.findItem(KMToolbarMeasureItemIdentifier)?.isSelected = true _ = CustomAlertView.alertView(message: "ESC to exit continuous measuring mode.", fromView: self.view, withStyle: .black) self.trackEvent(toolMode: .measureToolMode) } else { if let isVisible = distanceMeasureInfoWindowController!.window?.isVisible, isVisible { distanceMeasureInfoWindowController?.hideFloatingWindow() } else if let isVisible = perimeterMeasureInfoWindowController!.window?.isVisible, isVisible { perimeterMeasureInfoWindowController?.hideFloatingWindow() } else if let isVisible = areaMeasureInfoWindowController!.window?.isVisible, isVisible { areaMeasureInfoWindowController?.hideFloatingWindow() } self.toolbarController.findItem(KMToolbarMeasureItemIdentifier)?.isSelected = false } self.rightSideViewController.reloadDataWithPDFView(pdfView: listView, isShow: true) self.openRightPane() } } } // func showBatchWindow(type: KMBatchOperationType, files: [KMFileAttribute]?) { // let batchWindowController = KMBatchOperateWindowController.sharedWindowController //// batchWindowController.window?.makeKeyAndOrderFront("") // // var array: [KMBatchOperateFile] = [] // for file in files ?? [] { // let batchOperateFile = KMBatchOperateFile(filePath: file.filePath, type: type) // array.append(batchOperateFile) // } // batchWindowController.switchToOperateType(type, files: array) // batchWindowController.window?.makeKeyAndOrderFront("") // } func showBatchWindow(type: KMBatchOperationType, filepaths: [String]?) { let batchWindowController = KMBatchOperateWindowController.sharedWindowController var array: [KMBatchOperateFile] = [] for fpath in filepaths ?? [] { let batchOperateFile = KMBatchOperateFile(filePath: fpath, type: type) array.append(batchOperateFile) } batchWindowController.switchToOperateType(type, files: array) batchWindowController.window?.makeKeyAndOrderFront("") } func toolbarViewController(_ viewController: KMToolbarViewController, itemDidClick toolbarItem: KMToolbarItemView) { self.toolbarItemClickForExitMode(toolbarItem) if let itemID = toolbarItem.itemIdentifier { if isMainToolItem(itemID) { if toolbarItem.itemIdentifier == KMDocumentHomeToolbarItemIdentifier { openNewWindowAlertWindow() } else if toolbarItem.itemIdentifier == KMDocumentPreviousPageToolbarItemIdentifier { self.changePDFViewGoToPreviousPageAction() } else if toolbarItem.itemIdentifier == KMDocumentViewDisplayToolbarItemIdentifier { let isSelected = toolbarItem.isSelected self.toolbarController.toolbarType = isSelected ? .None : .viewSetting toolbarItem.isSelected = !isSelected if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageDisplay", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageDisplay_ViewSetting"]) self.rightSideViewController.isHidden = false self.rightSideViewController.mainController = self self.rightSideViewController.subViewType = .ViewSettings self.toolbarController.findItem(KMToolbarViewSettingIdentifier)?.isSelected = true self.openRightPane() }else{ self.rightSideViewController.isHidden = true self.rightSideViewController.subViewType = .AnnotationProperts closeRightPane() } if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn": "Btn_Tbr_PageDisplay"]) } let rightItem = self.toolbarController.findItem(KMRightControlToolbarItemIdentifier) if isSelected { rightItem?.isSelected = false } else { rightItem?.isSelected = true } } else if toolbarItem.itemIdentifier == KMLeftControlToolbarItemIdentifier { toolbarItem.isSelected = !toolbarItem.isSelected self.leftSideViewController.showPanelView(show: toolbarItem.isSelected) } else if toolbarItem.itemIdentifier == KMRightControlToolbarItemIdentifier { if (self.listView.activeAnnotation != nil) && (self.listView.activeAnnotation.type == "Image") { self.rightSideViewController.reloadDataWithPDFView(pdfView: self.listView, isShow: true) } toolbarItem.isSelected = !toolbarItem.isSelected self.toggleRightPane() if self.listView.toolMode == .editPDFToolMode { self.editPDFHanddler.rightSideLastState = toolbarItem.isSelected ? .open : .close } } else if itemID == KMDocumentRedactToolbarItemIdentifier { self.listView.toolMode = .redactToolMode self.enterRedact() } else if itemID == KMDocumentScanOCRToolbarItemIdentifier { showOCRWindow() } else if itemID == KMDocumentAIToolsToolbarItemIdentifier { self.showAITypeChooseView(aiConfigType: .none) } else if itemID == KMDocumentDigitalSignToolbarItemIdentifier { if self.canEnterDigitalSign() == false { Task { _ = await KMAlertTool.runModel(message: NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")) } return } toolbarItem.isSelected = !toolbarItem.isSelected self.toolbarController.lastItemBox = toolbarItem if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn": "Btn_Tbr_DigitalSignature"]) } self.enterDigitalSign() } else if itemID == KMDocumentPrintToolbarItemIdentifier { self.showPrintWindow() } else if itemID == KMDocumentPresentationToolbarItemIdentifier { self.enterPresentation() } else if itemID == KMDocumentSignToolbarItemIdentifier { let isSelected = toolbarItem.isSelected self.toolbarController.toolbarType = isSelected ? .None : .sign toolbarItem.isSelected = !isSelected self.toolbarController.lastItemBox = toolbarItem } } else { if toolbarItem.itemIdentifier == KMToolbarAnnotationSettingItemIdentifier { toolbarItem.isSelected = false let windowC = KMToolbarCustomWindowController() windowC.toolbar = self.toolbarController.childToolBarView?.toolbar windowC.resetCallback = { [weak self] in let toolbar = self?.toolbarController.childToolBarView?.toolbar toolbar?.reloadData() } self.km_beginSheet(windowC: windowC) { [weak self] resp, obj in if resp == .OK { let toolbar = self?.toolbarController.childToolBarView?.toolbar toolbar?.reloadData() } } } else if toolbarItem.itemIdentifier == KMToolbarComparisonItemIdentifier { Swift.debugPrint("KMToolbarComparisonItemIdentifier ...") } else if toolbarItem.itemIdentifier == KMDocumentPrintToolbarItemIdentifier { self.trackEvent_print() self.showPrintWindow() } else if toolbarItem.itemIdentifier == KMToolbarToolProfileIdentifier { Swift.debugPrint("KMToolbarToolProfileIdentifier ...") FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Fill&Sign", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Fill&Sign_Profile"]) let windowC = KMProfileInfoWindowController(windowNibName: "KMProfileInfoWindowController") windowC.callBack = { [weak self] string in if (string.isEmpty == false) { self?.listView.addTextField(subType: .profile, string: string) } self?.km_endSheet() } self.km_beginSheet(windowC: windowC) } else if toolbarItem.itemIdentifier == KMToolbarViewSettingIdentifier { toolbarItem.isSelected = !toolbarItem.isSelected rightSideViewController.mainController = self self.rightSideViewController.isHidden = toolbarItem.isSelected ? false : true self.rightSideViewController.subViewType = .ViewSettings // self.toggleRightPane() self.listView.annotationType = .unkown if toolbarItem.isSelected { self.rightSideViewController.isHidden = false self.rightSideViewController.mainController = self self.rightSideViewController.subViewType = .ViewSettings self.toolbarController.findItem(KMToolbarViewSettingIdentifier)?.isSelected = true self.openRightPane() }else{ self.rightSideViewController.isHidden = true self.rightSideViewController.subViewType = .AnnotationProperts closeRightPane() } } else if toolbarItem.itemIdentifier == KMToolbarSnapshotIdentifier { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageDisplay", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageDisplay_Snapshot"]) self.listView.takeSnapshot(nil) } else if toolbarItem.itemIdentifier == KMToolbarTTSIdentifier { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageDisplay", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageDisplay_TTS"]) self.listView.annotationType = .unkown self.showTTSWindow() } else if toolbarItem.itemIdentifier == KMToolbarConversionOCRIdentifier { self.showOCRWindow() } else if toolbarItem.itemIdentifier == KMAnnotationImageToolbarItemIdentifier { toolbarItem.isSelected = false self.imageAnnotation(toolbarItem) } else if toolbarItem.itemIdentifier == KMAnnotationTableToolbarItemIdentifier { self.tableAnnotation(toolbarItem) } else if toolbarItem.itemIdentifier == KMToolbarPageEditInsetItemIdentifier { // 插入 self.leftSideViewController.insertPDF(nil) } else if toolbarItem.itemIdentifier == KMToolbarPageEditSplitItemIdentifier { // 拆分 let windowC = SplitWindowController(document: self.listView.document) self.km_beginSheet(windowC: windowC) } else if itemID == KMSignDigitalSignToolbarItemIdentifier { if self.canEnterDigitalSign() == false { Task { _ = await KMAlertTool.runModel(message: NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")) } return } toolbarItem.isSelected = !toolbarItem.isSelected self.toolbarController.lastItemBox = toolbarItem if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn": "Btn_Tbr_DigitalSignature"]) } self.enterDigitalSign() } else if itemID == KMToolbarMeasureItemIdentifier { if toolbarItem.isSelected { toolbarItem.isSelected = false self.listView.toolMode = .textToolMode self.listView.annotationType = .unkown } } } } } func openNewWindowAlertWindow() { var needShowChooseWindow = false if (!KMMemberInfo.shared.isMemberAllFunction) { needShowChooseWindow = true } if needShowChooseWindow { let preferenceNoteShow = UserDefaults.standard.bool(forKey: KMTabbingHintShowFlag) if preferenceNoteShow { menuItemAction_newTagPageToNewWindow("") } else { if !KMDataManager.default.isTabbingWin{ KMDataManager.default.isTabbingWin = true let tabbingWin: KMTabbingHintWindowController = KMTabbingHintWindowController() tabbingWin.selectCallBack = {[weak self] continueOrNot in KMDataManager.default.isTabbingWin = false if continueOrNot { self?.reopenDocument(forPaths: []) } else { } } self.km_beginSheet(windowC: tabbingWin) } } }else{ handleTabbingLogic() } } func reopenDocument(forPaths paths: [String]) -> Void { let browser = KMBrowser.init() as KMBrowser browser.windowController = KMBrowserWindowController.init(browser: browser) browser.addHomeTabContents() browser.windowController.showWindow(self) } func handleTabbingLogic() { self.browserWindowController?.browser?.selectTabContents(at: 0, userGesture: true) self.toolbarController.findItem(KMDocumentHomeToolbarItemIdentifier)?.isSelected = false } func showTTSWindow() { var lastPDFView: CPDFView? let ttsView = KMTTSWindowController.share if (ttsView.window?.isVisible ?? false) { lastPDFView = ttsView.pdfView if lastPDFView?.document?.documentURL?.path == self.listView.document?.documentURL?.path { lastPDFView = nil ttsView.window?.orderOut(nil) } else { ttsView.pdfView = self.listView ttsView.showWindow(nil) } } else { ttsView.pdfView = self.listView ttsView.showWindow(nil) } // weak var blockSelf = self ttsView.closeWindowCallback = { (isCloseWindow: Bool) in if isCloseWindow { // for item in blockSelf?.toolbar.items ?? [] { // if item.itemIdentifier == KMToolbarTTSViewItemIdentifier { // item.isSelected = false // } // } } } if let currentSelection = self.listView.currentSelection { if let data = currentSelection.selectionsByLine, data.isEmpty == false { ttsView.startSpeakingPDFSelection(currentSelection) } } if let lastPDFView = lastPDFView { lastPDFView.setHighlightedSelections([]) ttsView.stopSpeaking() } } func toolbarViewController(_ viewController: KMToolbarViewController, menuItemDidClick toolbarItem: KMToolbarItemView, index: Int, info: Any?) { self.toolbarItemClickForExitMode(toolbarItem) let itemId = toolbarItem.itemIdentifier if (toolbarItem.itemIdentifier == KMToolbarToolWatermarkItemIdentifier) { self.clickChildTool(type: .watermark, index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Watermark"]) } else if (toolbarItem.itemIdentifier == KMToolbarToolBackgroundItemIdentifier) { self.clickChildTool(type: .background, index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Background"]) } else if (toolbarItem.itemIdentifier == KMToolbarToolHeaderFooterItemIdentifier) { self.clickChildTool(type: .headerAndFooter, index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Header&Footer"]) } else if (toolbarItem.itemIdentifier == KMToolbarToolBatesItemIdentifier) { self.clickChildTool(type: .bates, index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_BatesNumber"]) } else if (toolbarItem.itemIdentifier == KMToolbarMeasureItemIdentifier) { self.clickChildTool(type: .measure, index: index) } else if (toolbarItem.itemIdentifier == KMToolbarComparisonItemIdentifier) { self.clickChildTool(type: .comparison, index: index) } else if (toolbarItem.itemIdentifier == KMToolbarToolFormAlignIdentifier) { } else if (toolbarItem.itemIdentifier == KMToolbarConversionImageItemIdentifier) { convertToImg(index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Converter", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Converter_ToImage"]) } else if (toolbarItem.itemIdentifier == KMToolbarConversionExportImageItemIdentifier) { extractImageAction(num: index) } else if (toolbarItem.itemIdentifier == KMToolbarConversionCreatePDFItemIdentifier) { self.createPdf(index: index) } else if (toolbarItem.itemIdentifier == KMToolbarCropIdentifier) { if index == 2 { // 裁剪当前页面 self.cropCurrentPage() } else if index == 3 { // Auto Crop – Separate self.smart_cropAllPage() } else if index == 4 { // Auto Crop – Combined self.auto_cropAllPage() } else if index == 5 { // Select Area self.toolbarController.clickItem(KMToolbarSelectToolModeItemIdentifier) } FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageDisplay", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageDisplay_Crop"]) } else if (toolbarItem.itemIdentifier == KMToolbarToolSecureItemIdentifier) { self.clickChildTool(type: .secure, index: index) FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Security"]) } else if toolbarItem.itemIdentifier == KMDocumentSearchToolbarItemIdentifier { if index == 11 { self.view.window?.makeFirstResponder(nil) let winC = KMSearchReplaceWindowController(with: self.listView, type: .search) self.currentWindowController = winC winC.replaceCallback = { [weak self] in let toolMode = self?.listView?.toolMode ?? .none let isEditing = self?.listView?.isEditing() ?? false if toolMode == .editPDFToolMode && isEditing { } else { // 进入内容编辑模式 self?.toolbarController.clickItem(KMDocumentEditToolbarItemIdentifier) } } let point = toolbarItem.convert(toolbarItem.frame.origin, to: nil) // - (winC.window?.frame.size.width ?? 0) let x = point.x + (toolbarItem.window?.frame.origin.x ?? 0) - 200 let y = point.y + (toolbarItem.window?.frame.origin.y ?? 0) - 248 - 16 let winFramePoint = NSPoint(x: x, y: y) winC.window?.setFrameOrigin(winFramePoint) winC.startModal(nil) } else if index == 12 { if KMMemberInfo.shared.isMemberAllFunction == false { let winC = KMProductCompareWC.shared winC.kEventName = "Reading_ReplaceText_BuyNow" KMMemberInfo.shared.advancedFunctionUsage() return } self.view.window?.makeFirstResponder(nil) let toolMode = self.listView?.toolMode ?? .none let isEditing = self.listView?.isEditing() ?? false if toolMode == .editPDFToolMode && isEditing { } else { // 进入内容编辑模式 self.toolbarController.clickItem(KMDocumentEditToolbarItemIdentifier) } self.trackEvent_replace() let winC = KMSearchReplaceWindowController(with: self.listView, type: .replace) self.currentWindowController = winC winC.replaceCallback = { [weak self] in let toolMode = self?.listView?.toolMode ?? .none let isEditing = self?.listView?.isEditing() ?? false if toolMode == .editPDFToolMode && isEditing { } else { // 进入内容编辑模式 self?.toolbarController.clickItem(KMDocumentEditToolbarItemIdentifier) } } let point = toolbarItem.convert(toolbarItem.frame.origin, to: nil) let x = point.x + (toolbarItem.window?.frame.origin.x ?? 0) - 200 let y = point.y + (toolbarItem.window?.frame.origin.y ?? 0) - 388 let winFramePoint = NSPoint(x: x, y: y) winC.window?.setFrameOrigin(winFramePoint) winC.startModal(nil) } else { self.toolbarController.showFindBar() } } else if toolbarItem.itemIdentifier == KMRightControlToolbarItemIdentifier { toolbarItem.isSelected = !toolbarItem.isSelected self.toggleRightPane() } else if toolbarItem.itemIdentifier == KMDocumentViewDisplayToolbarItemIdentifier { self.toolbarController.toolbarType = .viewSetting } else if toolbarItem.itemIdentifier == KMToolbarConversionOCRIdentifier { self.showOCRWindow() } else if toolbarItem.itemIdentifier == KMToolbarAIItemIdentifier { if index == 1 { self.showAITypeChooseView(aiConfigType: .summarize) } else if index == 2 { self.showAITypeChooseView(aiConfigType: .reWriting) } else if index == 3 { self.showAITypeChooseView(aiConfigType: .proofreading) } else if index == 4 { self.showAITypeChooseView(aiConfigType: .translate) } } else if toolbarItem.itemIdentifier == KMDocumentScanOCRToolbarItemIdentifier { self.showOCRWindow() } else if toolbarItem.itemIdentifier == KMDocumentEditToolbarItemIdentifier { self.toolbarController.toolbarType = .editPDF self.enterEditPDF() } else if toolbarItem.itemIdentifier == KMDocumentFillSginToolbarItemIdentifier { self.toolbarController.toolbarType = .FillSign } else if toolbarItem.itemIdentifier == KMDocumentFormToolbarItemIdentifier { self.toolbarController.toolbarType = .Form } else if itemId == KMDocumentDigitalSignToolbarItemIdentifier { if self.canEnterDigitalSign() == false { Task { _ = await KMAlertTool.runModel(message: NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")) } return } toolbarItem.isSelected = !toolbarItem.isSelected self.toolbarController.lastItemBox = toolbarItem if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn": "Btn_Tbr_DigitalSignature"]) } self.enterDigitalSign() } else if itemId == KMSignDigitalSignToolbarItemIdentifier { if self.canEnterDigitalSign() == false { Task { _ = await KMAlertTool.runModel(message: NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "")) } return } toolbarItem.isSelected = !toolbarItem.isSelected self.toolbarController.lastItemBox = toolbarItem if toolbarItem.isSelected { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn": "Btn_Tbr_DigitalSignature"]) } self.enterDigitalSign() } else if itemId == KMDocumentAIToolsToolbarItemIdentifier { self.showAITypeChooseView(aiConfigType: .none) } else if itemId == KMToolbarToolCompressItemIdentifier { self.clickChildTool(type: .compress, index: 0) } else if itemId == KMToolbarPageEditSplitItemIdentifier { // 拆分 let windowC = SplitWindowController(document: self.listView.document) self.km_beginSheet(windowC: windowC) } else if itemId == KMToolbarToolMergeItemIdentifier { self.clickChildTool(type: .merge, index: 0) } else if itemId == KMToolbarPageEditInsetItemIdentifier { self.leftSideViewController.insertPDF(nil) } else if itemId == KMToolbarShowToolbarItemIdentifier { self.showOrHideNotes() } else if itemId == KMAnnotationTableToolbarItemIdentifier { self.tableAnnotation(toolbarItem) } else if itemId == KMToolbarConversionTextItemIdentifier { self.clickChildTool(type: .conversion_text, index: 0) } else if itemId == KMToolbarConversionHTMLItemIdentifier { self.clickChildTool(type: .html, index: 0) } else if itemId == KMToolbarConversionCSVItemIdentifier { self.clickChildTool(type: .csv, index: 0) } else if itemId == KMToolbarConversionRTFItemIdentifier { self.clickChildTool(type: .rtf, index: 0) } else if itemId == KMToolbarConversionPPTItemIdentifier { self.clickChildTool(type: .ppt, index: 0) } else if itemId == KMToolbarConversionExcelItemIdentifier { self.clickChildTool(type: .excel, index: 0) } else if itemId == KMToolbarConversionWordItemIdentifier { self.clickChildTool(type: .word, index: 0) } else if itemId == KMToolbarConversionOtherItemIdentifier { if index == KMPDFConvertType.text.rawValue { self.clickChildTool(type: .conversion_text, index: 0) } else if index == KMPDFConvertType.rtf.rawValue { self.clickChildTool(type: .rtf, index: 0) } else if index == KMPDFConvertType.html.rawValue { self.clickChildTool(type: .html, index: 0) } else if index == KMPDFConvertType.csv.rawValue { self.clickChildTool(type: .csv, index: 0) } else if index == KMPDFConvertType.json.rawValue { self.clickChildTool(type: .json, index: 0) } } } func convertToImg(index: Int) { var convertT: KMConvertType = .JPEG switch index { case 7: convertT = .JPEG case 8: convertT = .JPG case 9: convertT = .PNG case 10: convertT = .GIF case 11: convertT = .TIFF case 12: convertT = .TGA case 13: convertT = .BMP default: convertT = .JPEG } showAllConvertWindow(convertT: convertT) } func toolbarViewController(_ viewController: KMToolbarViewController, searchAction searchString: String, forward: Bool) { // if self.searchResults.count == 0 { // let caseInsensitive = UserDefaults.standard.bool(forKey: "SKCaseInsensitiveFindKey") let caseInsensitive = UserDefaults.standard.bool(forKey: SKCaseInsensitiveSearchKey) self.search(searchString: searchString, isCase: caseInsensitive, display: false) // } var row = max(searchIndex - 1, 0) if forward { row = searchIndex + 1 } if row >= 0 && row < self.searchResults.count && self.searchResults.count != 0 { let model = self.searchResults[row] if model.selection != nil { self.listView.setHighlightedSelections([]) self.listView.go(to: model.selection, animated: true) self.listView.setHighlightedSelection(model.selection, animated: true) self.listView.setNeedsDisplayAnnotationViewForVisiblePages() searchIndex = row } } self.leftSideViewController.showSearchMode(searchString) } func toolbarViewController(_ viewController: KMToolbarViewController, findSearchAction searchString: String, forward: Bool) { // if self.searchResults.count == 0 { // let caseInsensitive = UserDefaults.standard.bool(forKey: "SKCaseInsensitiveFindKey") let caseInsensitive = UserDefaults.standard.bool(forKey: SKCaseInsensitiveSearchKey) self.search(searchString: searchString, isCase: !caseInsensitive, display: false) // } var row = max(searchIndex - 1, 0) if forward { row = searchIndex + 1 } if row >= 0 && row < self.searchResults.count && self.searchResults.count != 0 { let model = self.searchResults[row] if model.selection != nil { self.listView.setHighlightedSelections([]) self.listView.go(to: model.selection, animated: true) self.listView.setHighlightedSelection(model.selection, animated: true) self.listView.setNeedsDisplayAnnotationViewForVisiblePages() searchIndex = row } } } func toolbarViewController(_ viewController: KMToolbarViewController, findSearchAllAction searchString: String, forward: Bool) { let caseInsensitive = UserDefaults.standard.bool(forKey: SKCaseInsensitiveSearchKey) self.search(searchString: searchString, isCase: !caseInsensitive, display: false, needShowAll: true) self.leftSideViewController.showSearchMode(searchString) } func toolbarViewController(_ viewController: KMToolbarViewController, viewItemDidClick toolbarItem: KMToolbarItemView, index: Int, info: Any?) { let itemId = toolbarItem.itemIdentifier if itemId == KMDocumentFirstLastToolbarItemIdentifier { if index == 1 { if self.listView.canGoToFirstPage() { self.listView.goToFirstPage(nil) } } else if index == 2 { if self.listView.canGoToLastPage() { self.listView.goToLastPage(nil) } } } else if itemId == KMDocumentPageInputToolbarItemIdentifier { var valid = false if let number = Int(info as? String ?? "") { let cnt = self.listView?.document?.pageCount ?? 0 if number > 0 && number <= cnt { self.listView.go(toPageIndex: number-1, animated: false) valid = true } } if valid == false { Task {@MainActor in _ = await KMAlertTool.runModel(message: NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")) } } } } } // MARK: CDistanceMeasureInfoWindowControllerDelegate extension KMMainViewController : CDistanceMeasureInfoWindowControllerDelegate { func distanceMeasureInfoWindowControllerSetting(_ distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController) { let distanceSettingWC = CDistanceSettingWindowController(distanceMeasureInfo: self.distanceMeasureInfoWindowController!.measureInfo) self.distanceMeasureInfoWindowController?.hideFloatingWindow() distanceSettingWC.delegate = self distanceSettingWC.startModal("") } func cancelMeasureInfoWindowControllerSetting(_ distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController) { } } // MARK: CPerimeterMeasureInfoWindowControllerDelegate extension KMMainViewController : CPerimeterMeasureInfoWindowControllerDelegate { func perimeterMeasureInfoWindowControllerSetting(_ perimeterMeasureInfoWindowController: CPerimeterMeasureInfoWindowController) { let distanceSettingWC = CDistanceSettingWindowController(perimeterMeasureInfo: self.perimeterMeasureInfoWindowController!.measureInfo) self.distanceMeasureInfoWindowController?.hideFloatingWindow() distanceSettingWC.delegate = self distanceSettingWC.startModal("") } } // MARK: CAreaMeasureInfoWindowControllerDelegate extension KMMainViewController : CAreaMeasureInfoWindowControllerDelegate { func areaMeasureInfoWindowControllerSetting(_ areaMeasureInfoWindowController: CAreaMeasureInfoWindowController) { let areaSettingWC = CAreaSettingWindowController(measureInfo: self.areaMeasureInfoWindowController!.measureInfo) self.areaMeasureInfoWindowController?.hideFloatingWindow() areaSettingWC.delegate = self areaSettingWC.startModal("") } } // MARK: CDistanceSettingWindowControllerDelegate extension KMMainViewController : CDistanceSettingWindowControllerDelegate { func distanceSettingWindowController(_ distanceSettingWindowController: CDistanceSettingWindowController, distanceMeasureInfo: CPDFDistanceMeasureInfo?) { if distanceMeasureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFLineAnnotation.self) { (self.listView.activeAnnotation as! CPDFLineAnnotation).measureInfo = distanceMeasureInfo self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.distanceMeasureInfoWindowController?.reloadData(with: (self.listView.activeAnnotation as! CPDFLineAnnotation).measureInfo!) } else { distanceMeasureInfo?.leadLength = 0 self.listView.distanceMeasureInfo = distanceMeasureInfo self.distanceMeasureInfoWindowController?.reloadData(with: self.listView.distanceMeasureInfo) self.distanceMeasureInfoWindowController?.lengthLabel.stringValue = "" self.distanceMeasureInfoWindowController?.angleLabel.stringValue = "" self.distanceMeasureInfoWindowController?.xLabel.stringValue = "" self.distanceMeasureInfoWindowController?.yLabel.stringValue = "" } if let data = self.listView?.activeAnnotation { self.leftSideViewController.refreshUIForAnnoAttributeDidChange(data, attributes: nil) } } self.distanceMeasureInfoWindowController?.showWindow(self) } func distanceSettingWindowController(_ distanceSettingWindowController: CDistanceSettingWindowController, perimeterMeasureInfo: CPDFPerimeterMeasureInfo?) { if perimeterMeasureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFPolylineAnnotation.self) { (self.listView.activeAnnotation as! CPDFPolylineAnnotation).measureInfo = perimeterMeasureInfo self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.perimeterMeasureInfoWindowController?.reloadData(with: (self.listView.activeAnnotation as! CPDFPolylineAnnotation).measureInfo!) } else { self.listView.perimeterMeasureInfo = perimeterMeasureInfo self.perimeterMeasureInfoWindowController?.reloadData(with: self.listView.perimeterMeasureInfo) self.perimeterMeasureInfoWindowController?.lengthLabel.stringValue = "" self.perimeterMeasureInfoWindowController?.angleLabel.stringValue = "" } if let data = self.listView?.activeAnnotation { self.leftSideViewController.refreshUIForAnnoAttributeDidChange(data, attributes: nil) } } self.perimeterMeasureInfoWindowController?.showWindow(self) } } // MARK: CAreaSettingWindowControllerDelegate extension KMMainViewController : CAreaSettingWindowControllerDelegate { func areaSettingWindowController(_ areaSettingWindowController: CAreaSettingWindowController, measureInfo: CPDFAreaMeasureInfo?) { if self.listView.annotationType == .square && self.listView.toolMode == .measureToolMode { if measureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) { (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!) } else { self.listView.squareAreaMeasureInfo = measureInfo self.areaMeasureInfoWindowController?.reloadData(self.listView.squareAreaMeasureInfo) self.areaMeasureInfoWindowController?.areaLabel.stringValue = "" self.areaMeasureInfoWindowController?.angleLabel.stringValue = "" } } self.areaMeasureInfoWindowController?.showWindow(self) } else if self.listView.annotationType == .polyGon && self.listView.toolMode == .measureToolMode { if measureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) { (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!) } else { self.listView.polygonAreaMeasureInfo = measureInfo self.areaMeasureInfoWindowController?.reloadData(self.listView.polygonAreaMeasureInfo) self.areaMeasureInfoWindowController?.areaLabel.stringValue = "" self.areaMeasureInfoWindowController?.angleLabel.stringValue = "" } } self.areaMeasureInfoWindowController?.showWindow(self) } else { if measureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) { (self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo = measureInfo self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.areaMeasureInfoWindowController?.reloadData((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo!) } } self.areaMeasureInfoWindowController?.showWindow(self) } if measureInfo != nil { if let data = self.listView?.activeAnnotation { self.leftSideViewController.refreshUIForAnnoAttributeDidChange(data, attributes: nil) } } } } // MARK: - // MARK: - Mouse extension KMMainViewController { override func mouseDown(with event: NSEvent) { super.mouseDown(with: event) // KMPrint("KMMainViewController mouseDown") self.leftSideViewCancelSelect() self.pageNumberDisplayView.isEdit = false } } //MARK: LeftSideViewController extension KMMainViewController { func leftSideViewCancelSelect() { // switch self.leftSideViewController.type.methodType { // case .Thumbnail: //// self.leftSideViewController.thumbnailViewController.cancelSelect() // break // case .Outline: //// self.leftSideViewController.outlineViewController.cancelSelect() // break // case .BookMark: //// self.leftSideViewController.bookViewController.cancelSelect() // break // case .Search: //// self.leftSideViewController.searchViewController.cancelSelect() // break // case .Annotation: //// self.leftSideViewController.annotationViewController.cancelSelect() // break // default: if self.listView.isEditing() { if self.listView.editingAreas() != nil && self.listView.editingAreas().count != 0 { let areas = self.listView.editingAreas().first if areas is CPDFEditTextArea { self.listView.clearEditingSelectCharItem() self.listView.updateEditing([]) KMPrint("取消选中") } } } // KMPrint("其他") // } } } extension KMMainViewController: KMReadModelViewDelegate { func firstPageButtonDidChange(view: KMReadModelView, sender: Any) { self.listView.goToFirstPage(nil) } func beforePageButtonDidChange(view: KMReadModelView, sender: Any) { self.listView.goToPreviousPage(nil) } func afterPageButtonDidChange(view: KMReadModelView, sender: Any) { self.listView.goToNextPage(nil) } func lastPageButtonDidChange(view: KMReadModelView, sender: Any) { self.listView.goToLastPage(nil) } func currentPageButtonDidChange(view: KMReadModelView, sender: Any, pageIndex: Int) { self.listView.go(toPageIndex: max(pageIndex - 1, 0), animated: true) } func scaleDidChange(view: KMReadModelView, sender: Any, type: KMReadModelViewScaleType) { var scale: Double = 1.0 switch type { case .fitWidth: self.listView.autoScales = !self.listView.autoScales scale = self.listView.scaleFactor break case .actualSize: if self.listView.scaleFactor != 1.0 { self.listView.scaleFactor = 1.0 self.listView.autoScales = false } scale = self.listView.scaleFactor break case .autoSize: self.listView.autoScales = true self.listView.autoScales = false scale = self.listView.scaleFactor break case ._10: scale = 0.1 break case ._25: scale = 0.25 break case ._50: scale = 0.5 break case ._100: scale = 1.0 break case ._150: scale = 1.5 break case ._200: scale = 2.0 break case ._400: scale = 4.0 break case ._800: scale = 8.0 break default: break } self.listView.scaleFactor = scale self.toolbarController.mainViewController?.childToolbarController.zoomTextField?.stringValue = "\(Int(self.listView.scaleFactor*100))%" } func cancelReadModel(view: KMReadModelView, sender: Any) { if self.isReadMode { self.closeReadModel() } } func readModelViewWidthChange(view: KMReadModelView, width: CGFloat) { // if self.readModelViewWidthConstraint.constant != width { self.readModelViewWidthConstraint.constant = width // } } // MARK: - KMPresentationTopViewController (幻灯片) func presentationTopViewExit(_ presentationTopViewController: KMPresentationTopViewController, withButton: NSButton) { if self.canExitPresentation() == true { let mainDocument = self.myDocument as? KMMainDocument let browserWindowController = mainDocument?.browser?.windowController as? KMBrowserWindowController browserWindowController?.exitFullscreen() } } func presentationTopViewClear(_ presentationTopViewController: KMPresentationTopViewController, withButton: NSButton) { listView.presentationDrawView?.clear() } func presentationTopViewUndo(_ presentationTopViewController: KMPresentationTopViewController, withButton: NSButton) { let presentationDrawView = listView.presentationDrawView if presentationDrawView?.canUndo() == true { presentationDrawView?.undo() } } func presentationTopViewType(_ presentationTopViewController: KMPresentationTopViewController, withButton: NSButton, isSeletion: Bool) { listView.isPresentationMode = isSeletion if listView.isEnterPresentationDrawMode() == true { listView.exitPresentationDrawMode() } } func presentationTopViewDrawColor(_ presentationTopViewController: KMPresentationTopViewController, withView: NSView,color:NSColor?) { if color == nil{ listView.exitPresentationDrawMode() } else { if listView.isEnterPresentationDrawMode() == false { listView.enterPresentationDrawMode() } listView.changePresentationDrawModelColor(color) } } } extension KMMainViewController: KMPageNumberDisplayViewDelegate { func gotoPageIndex(view: KMPageNumberDisplayView, pageIndex: Int) { self.listView.go(toPageIndex: pageIndex, animated: true) } func updateWidth(view: KMPageNumberDisplayView, width: CGFloat) { if self.tipCurrentPageBoxWidthConstraint.constant != width { self.tipCurrentPageBoxWidthConstraint.constant = width } } func commitEditingIfNeed() { self.editPDFHanddler.commitEditing() } } extension KMMainViewController: KMInteractionProviderProtocol { func providerContentView(fullScreenWindow: NSWindow, inset: CGFloat) -> NSView? { let view = self.listView if(interactionMode == .presentation) { if view?.presentationDrawView == nil { view?.createPresentationDraw() } presentationTopViewController = KMPresentationTopViewController.init(nibName: "KMPresentationTopViewController", bundle: nil) presentationTopViewController?.pdfView = view presentationTopViewController?.delegate = self presentationTopViewController?.isSelectionPre = true listView.isPresentationMode = true presentationTopViewController?.view.frame = CGRect(x: 0, y: (fullScreenWindow.contentView?.bounds.height ?? 0) - 42, width: fullScreenWindow.contentView?.bounds.width ?? 0, height: 42) if((presentationTopViewController) != nil) { fullScreenWindow.contentView?.addSubview(presentationTopViewController!.view) } } else { view?.frame = NSInsetRect(fullScreenWindow.contentView?.bounds ?? .zero, 0, 0) } if let v = view { fullScreenWindow.contentView?.addSubview(v) if(interactionMode == .presentation) { v.mas_makeConstraints { make in make?.left.mas_equalTo()(0) make?.right.mas_equalTo()(0) make?.top.mas_equalTo()(presentationTopViewController!.view.frame.height) make?.bottom.mas_equalTo()(0) } } } return view } } // MARK: - Analytics (埋点) extension KMMainViewController { func trackEvent(toolType type: KMToolbarViewType) -> Void { if (type == .Annatiton) { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn" : "Btn_Tbr_Tools"]) } else if (type == .editPDF) { } else if (type == .Page) { FMTrackEventManager.defaultManager.trackEvent(event: "Tbr", withProperties: ["Tbr_Btn" : "Btn_Tbr_PageEdit"]) } else if (type == .Conversion) { } else if (type == .Tool) { } } func trackEvent_aiTranslate() -> Void { KMAnalytics.trackEvent(eventName: "Btn_Tbr_AITranslate", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent_print() -> Void { KMAnalytics.trackEvent(eventName: "Btn_Tbr_Print", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent_share() -> Void { KMAnalytics.trackEvent(eventName: "Btn_Tbr_Share", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent_upgrade() -> Void { KMAnalytics.trackEvent(eventName: "Btn_Tbr_Upgrade", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.tbr, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.tbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent(annotationType type: CAnnotationType) -> Void { if (type == .highlight) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Highlight"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Highlight", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .underline) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Underline"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Underline", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .strikeOut) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Strikethrough"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Strikethrough", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .ink) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Freehand"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Draw", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .freeText) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_TextBox"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Text", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .anchored) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_AnchoredNote"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Note", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .square) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Rectangle"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Shape", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .link) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Link"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Link", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .stamp) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Stamp"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Stamp", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .signSignature) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Signature"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Sign", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .circle) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Oval"]) } else if (type == .arrow) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Arrow"]) } else if (type == .line) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Line"]) } else if (type == .addText) { KMAnalytics.trackEvent(eventName: "Btn_SubTbr_AddText", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_editPDF, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .addImage) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Image"]) // KMAnalytics.trackEvent(eventName: "Btn_SubTbr_AddImage", parameters: [ // KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_editPDF, // KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (type == .textField) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_TextField"]) } else if (type == .checkBox) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_CheckBox"]) } else if (type == .radioButton) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_RadioButton"]) } else if (type == .listMenu) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_ListBox"]) } else if (type == .comboBox) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_ComboBox"]) } else if (type == .actionButton) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Button"]) } else if (type == .actionButton) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Button"]) } else if (type == .signature) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Form", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Form_Signature"]) } else if (type == .squiggly) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Squiglly"]) } else if (type == .eraser) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Tools_Erasder"]) } } func trackEvent(toolMode mode: CToolMode) -> Void { if (mode == .selectToolMode) { KMAnalytics.trackEvent(eventName: "Btn_SubTbr_ContentSelection", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if (mode == .moveToolMode) { KMAnalytics.trackEvent(eventName: "Btn_SubTbr_Scroll", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_annotation, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } else if mode == .measureToolMode { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn" : "Btn_SubTbr_Editor_Measure"]) } } func trackEvent(toolBarType type: KMToolbarType) -> Void { if (type == .word) { } else if (type == .excel) { } else if (type == .ppt) { } else if (type == .rtf) { } else if (type == .csv) { } else if (type == .html) { } else if (type == .conversion_text) { } else if (type == .conversion_image) { } else if (type == .compress) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Editor", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Editor_Compress"]) } else if (type == .merge) { } else if (type == .secure) { } else if (type == .crop) { } else if type == .json { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Converter", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Converter_ToOthers_ToJson"]) } } func trackEvent_setPassword() -> Void { KMAnalytics.trackEvent(eventName: "Btn_SubTbr_SetPassword", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_Tools, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent_removePassword() -> Void { KMAnalytics.trackEvent(eventName: "Btn_SubTbr_RemovePassword", parameters: [ KMAnalytics.Parameter.categoryKey : KMAnalytics.Category.subTbr_Tools, KMAnalytics.Parameter.labelKey : KMAnalytics.Label.subTbr_Btn], platform: .AppCenter, appTarget: .all) } func trackEvent_replace() -> Void { self.trackEvent(eventName: "Tbr", params: ["Tbr_Btn" : "Btn_Tbr_ReplaceText"], platform: .AppCenter) } } extension KMMainViewController { //文件对比 func openContentCompareVC(with pdfCompareContent: CPDFCompareContent?, results: [CPDFCompareResults], oldDocument: CPDFDocument, document: CPDFDocument) { self.isCompareModel = true let compareContentView = KMCompareContentView() compareContentView.oldDocument = oldDocument compareContentView.document = document compareContentView.compareResults = results compareContentView.saveHandle = { [unowned self] view in DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.25) { [unowned self] in let saveController = KMCompareSaveWindow(windowNibName: "KMCompareSaveWindow") self.currentWindowController = saveController saveController.cancelHandle = { [unowned self] controller in self.view.window!.endSheet(controller.window!) self.currentWindowController = nil } saveController.saveHandle = { [unowned self] controller, saveType in let folderPath = controller.fileSaveFolderPath if folderPath != nil { if !FileManager.default.fileExists(atPath: folderPath) { try? FileManager.default.createDirectory(atPath: folderPath, withIntermediateDirectories: true, attributes: nil) } #if VERSION_DMG #else let url = URL(fileURLWithPath: folderPath) let fileAccess = AppSandboxFileAccess() fileAccess?.persistPermissionURL(url) if let bookmarkData = try?url.bookmarkData(options: [.withSecurityScope]) { fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: url) let urlString = url.path let _url = URL(fileURLWithPath: urlString) fileAccess?.bookmarkPersistanceDelegate.setBookmarkData(bookmarkData, for: _url) } #endif var savePath: String switch saveType { case 0: let filePath = oldDocument.documentURL.path let fileName = filePath.deletingPathExtension.lastPathComponent savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)" savePath = self.getValidFilePath(savePath) oldDocument.write(to: URL(fileURLWithPath: savePath)) NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)]) case 1: let filePath = document.documentURL.path let fileName = filePath.deletingPathExtension.lastPathComponent savePath = "\(folderPath)/\(fileName)_compare\(filePath.extension)" savePath = self.getValidFilePath(savePath) document.write(to: URL(fileURLWithPath: savePath)) NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)]) case 2: let filePath = oldDocument.documentURL.path let fileName = filePath.deletingPathExtension.lastPathComponent savePath = "\(folderPath)/MergedCompareFile\(filePath.extension)" savePath = self.getValidFilePath(savePath) pdfCompareContent!.saveAsComparisonDocument(withFilePath: savePath) NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: savePath)]) default: break } } self.view.window!.endSheet(controller.window!) self.currentWindowController = nil } NSWindow.currentWindow().beginSheet(saveController.window!) } } compareContentView.closeHandle = { [unowned self] view in // self.view.window!.endSheet(controller.window!) self.isCompareModel = false view.removeFromSuperview() } self.PDFContendView.addSubview(compareContentView) compareContentView.frame = self.PDFContendView.bounds compareContentView.autoresizingMask = [.width,.height] } func openCoveringCompareVC(with pdfDocument: CPDFDocument) { self.isCompareModel = true let coveringView = KMCompareCoveringView() coveringView.pdfDocument = pdfDocument coveringView.closeHandle = { [unowned self] view in self.isCompareModel = false view.removeFromSuperview() } coveringView.saveHandle = { [unowned self] view in let savePanel = NSSavePanel() savePanel.nameFieldStringValue = "untitled" savePanel.allowedFileTypes = ["pdf"] savePanel.beginSheetModal(for: NSWindow.currentWindow()) { result in if result == .OK { pdfDocument.write(to: savePanel.url!) NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!]) } } } self.PDFContendView.addSubview(coveringView) coveringView.frame = self.PDFContendView.bounds coveringView.autoresizingMask = [.width,.height] } func getValidFilePath(_ oldPath: String) -> String { let fileManager = FileManager.default do { let fileAttributes = try fileManager.attributesOfItem(atPath: oldPath) guard let fileType = fileAttributes[FileAttributeKey.type] as? String else { return oldPath } var i = 1 var newPath = oldPath while fileManager.fileExists(atPath: newPath) { if fileType == FileAttributeType.typeDirectory.rawValue { newPath = oldPath + "(\(i))" } else { let fileExtension = (oldPath as NSString).pathExtension newPath = ((oldPath as NSString).deletingPathExtension as NSString).appendingFormat("(\(i)).\(fileExtension)" as NSString) as String } i += 1 } return newPath } catch { print("Error getting file attributes: \(error)") return oldPath } } } extension KMMainViewController { func documentAllowsEdit() -> Bool { if (self.listView.document.allowsCopying == false || self.listView.document.allowsPrinting == false) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return false } else { return true } } }