// // 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) { } func removeSignatures(signatures:[CPDFSignature]) { for signature in signatures { self.listView.document.removeSignature(signature) } for i in 0.. 0 { mSignatures.append(sign) } } } 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 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 useNativeFullScreen() -> Bool { var isFull = false let sel = NSSelectorFromString("toggleFullscreen:") if NSWindow.instancesRespond(to: sel) && UserDefaults.standard.bool(forKey: "SKUseLegacyFullScreenKey"){ isFull = true } return isFull } //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("添加文字") } else if sender.tag == 1 { } else if sender.tag == 2 { KMPrint("粘贴") } } @objc func menuItemEditingClick_CropImage(sender: NSMenuItem) { if self.listView.cropAreas != nil && self.listView.selectImageAreas != nil{ self.listView.cropEditImageArea(self.listView.selectImageAreas, withBounds: self.listView.cropAreas.cropRect) } } @objc func menuItemAnnotationClick_toolModel(sender: NSMenuItem) { } @objc func changeAnnotationMode_itemAction(sender : NSMenuItem) { } @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: 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 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 menuItemAnnotationClick_addStype(sender: NSMenuItem) { Task { @MainActor in let idx = sender.tag if idx == 10 { if IAPProductsManager.default().isAvailableAllFunction() == false { KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) 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 viewManager.isPDFReadMode { if (sender.tag == 0 || sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign self.listView.toolMode = .CNoteToolMode } switch sender.tag { case 0: self.listView.annotationType = CAnnotationType.ink case 1: 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: 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: 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: 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: 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: 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 toggleOpenRightSide() case 8: self.listView.annotationType = CAnnotationType.stamp toggleOpenRightSide() case 9: self.listView.annotationType = CAnnotationType.signSignature toggleOpenRightSide() default: break } } else { if (sender.tag == 7 || sender.tag == 8 || sender.tag == 9) { // Ink & Link & stamp & sign self.listView.toolMode = .CNoteToolMode } switch sender.tag { case 0: self.listView.toolMode = .CNoteToolMode self.listView.annotationType = CAnnotationType.ink case 1: 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) if ((annotation) != nil) { self.listView.edit(annotation) } case 2: 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: 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: 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: 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: 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 toggleOpenRightSide() case 8: self.listView.annotationType = CAnnotationType.stamp toggleOpenRightSide() case 9: self.listView.annotationType = CAnnotationType.signSignature toggleOpenRightSide() case 10: self.addImgAnnotationToView(center: pagePoint) default: break } if annotation != nil{ self.listView.activeAnnotations.removeAllObjects() var newAnnonations : [CPDFAnnotation] = [] newAnnonations.append(annotation!) self.listView.updateActiveAnnotations(newAnnonations) } } } } 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) } } } // 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 } } func showMeasurePerimeterSettingWindow(measureInfo: CPDFPerimeterMeasureInfo?, hideInfoWindow: Bool = true) { guard let mInfo = measureInfo else { return } } func showMeasureAreaSettingWindow(measureInfo: CPDFAreaMeasureInfo?, hideInfoWindow: Bool = true) { guard let mInfo = measureInfo else { return } } // 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() 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) } 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 fullScreenWindow.display() fadeWindow.fadeOut() } @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 == .CSelectToolMode { objc_sync_enter(self) self.listView.selectionRect = NSZeroRect self.listView.selectionPageIndex = UInt(NSNotFound) objc_sync_exit(self) } } //MARK: - action 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) 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 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 closeTab(_ sender: NSNotification) -> Void { } @IBAction func toggleSplitPDF(_ sender: Any) { } // MARK: - 图片注释 @IBAction func imageAnnotation(_ sender: Any) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Image"]) guard IAPProductsManager.default().isAvailableAllFunction() else { KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) 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") { } } } } @IBAction func tableAnnotation(_ sender: Any) { FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_Tools", withProperties: ["SubTbr_Btn": "Btn_SubTbr_Tools_Table"]) guard IAPProductsManager.default().isAvailableAllFunction() else { let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.kEventName = "Reading_Table_BuyNow" winC?.showWindow(nil) return } listView.addAnnotationWithTable() toggleOpenRightSide() } 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))" } } extension KMMainViewController { func changeModelAction(mode: CToolMode) { self.listView.toolMode = mode if mode == .CEditPDFToolMode { } } func aiTranslationPDFFileAction() { 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!) { [weak self] result in if (result == .alertFirstButtonReturn) { } else if result == .alertSecondButtonReturn { return } } } func openNewWindowAlertWindow() { var needShowChooseWindow = false //#if VERSION_FREE if (!IAPProductsManager.default().isAvailableAllFunction()) { needShowChooseWindow = true } //#endif if needShowChooseWindow { let preferenceNoteShow = UserDefaults.standard.bool(forKey: KMTabbingHintShowFlag) if preferenceNoteShow { } 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) } } //MARK: LeftSideViewController extension KMMainViewController { func leftSideViewCancelSelect() { if self.listView.isEditing() == true { 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("取消选中") } } } } } 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 } } func changeFont(_ sender: NSFontManager) { KMPrint("changeFont ...") if ((self.listView.activeAnnotation?.isKind(of: CPDFFreeTextAnnotation.self)) != nil) { let annotation: CPDFFreeTextAnnotation = self.listView.activeAnnotation as! CPDFFreeTextAnnotation var font = NSFont(name: annotation.fontName() ?? "Helvetica", size: (annotation.fontSize()) ) font = sender.convert(font!) annotation.fontSize = font?.pointSize ?? 12 self.listView.commitEditAnnotationFreeText(annotation) self.listView.setNeedsDisplay(annotation) } } func currentSetup() -> [String: Any] { var setup: [String: Any] = [:] var point = NSZeroPoint if listView == nil { return setup } let pageIndex = listView.currentPageIndexAndPoint(&point, rotated: nil) setup[kWindowFrameKey] = NSStringFromRect(mainWindow?.frame ?? NSZeroRect) setup[KMMainModel.Key.pageIndex] = pageIndex return setup } }