// // KMMainViewController.swift // PDF Reader Pro // // Created by wanjun on 2022/12/15. // import Cocoa import KMComponentLibrary let MIN_SIDE_PANE_WIDTH: NSNumber = 264 // 最小值 let CPDFViewIsReadModeKey = "kKMPDFViewIsReadMode" let CPDFViewLeftSidePaneWidthKey = "CPDFOfficeLeftSidePaneWidthKey" struct KMNMWCFlags { var settingUpWindow: Bool = true } @objcMembers class KMMainViewController: KMNBaseViewController, NSTextFieldDelegate { @IBOutlet var contendBox: NSBox! @IBOutlet var toolbarBox: NSBox! //工具栏Box @IBOutlet var bottomContendBox: NSBox! // @IBOutlet var sidebarBox: NSBox! //左侧边栏Box @IBOutlet var infoContendSplitView: NSSplitView! @IBOutlet var infoSplitLeftView: NSView! @IBOutlet var infoSplitRightView: NSView! @IBOutlet var infoSplitCenterView: NSView! @IBOutlet var pdfSplitView: NSSplitView! @IBOutlet var pdfSplitTopView: NSView! @IBOutlet var pdfSplitBottomView: NSView! @IBOutlet var toolbarBoxHeightConst: NSLayoutConstraint! @IBOutlet var infoSplitViewLeftConst: NSLayoutConstraint! @IBOutlet var infoSplitViewRightConst: NSLayoutConstraint! var viewManager: KMPDFViewManager = KMPDFViewManager.init() var toolbarManager: KMPDFToolbarManager = KMPDFToolbarManager.init() var listView: CPDFListView = CPDFListView.init() var document: CPDFDocument? var myDocument: NSDocument? var isFirstOpen: Bool = true var insertDocuments: Set = [] //插入新文档时,SDK会出现崩溃,临时记录 //工具栏 private var pdfToolbarController: KMPDFToolbarController? //BOTA SideBar private var sideBarController: KMPDFSideBarController? //页面编辑 private var pageEditViewController: KMNPageEditViewController? //DisplaySetting private var displaySettingController: KMNDisplayViewController? //SPlitPDF分屏视图 private var splitPDFController: KMSplitPDFViewController? private var pageNumberToolbar: KMPageNumberPromptView? //PPT操作界面 var presentationTopViewController: KMPresentationTopViewController? //Edit var editToolbarView: KMEditToolbarView? //水印 var watermarkViewController: KMWatermarkController? //背景 var backgroundViewController: KMBackgroundController? //Header&Footer var headerFooterViewController: KMHeaderFooterController? //Bates var batesViewController: KMBatesController? //Crop var cropController: KMCropController? //左边 var botaViewController: KMNLeftSideViewController? //右边 var rightSideController: KMRightSideController? let alertTipViewController: KMNAlertTipViewController = KMNAlertTipViewController(nibName: "KMNAlertTipViewController", bundle: nil) //合并 var mergeWindowController: KMMergeWindowController? //春季活动 var recommondPopWindowVC: KMRecommondPopWindow? //数字签名状态 var signaturestateVC: CDSignatureCertificateStateViewController = CDSignatureCertificateStateViewController.init() //PDFView右键菜单 private var groupListMenuGroup: ComponentGroup? = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle()) var textFieldSheet: KMTextFieldSheetController = KMTextFieldSheetController.init(windowNibName: "KMTextFieldSheetController") @IBOutlet weak var leftView: NSView! var model = KMMainModel() //Search var searchIndex: Int = 0 //对比 var isCompareModel: Bool = false //密码弹窗 var passwordWindow: KMPasswordInputWindow? var securityWindowController: KMSecurityWindowController? //压缩 var compressWindowController: KMCompressWindowController? //引导 var guideInfoWindowController: KMGuideInfoWindowController? //测量 var distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController? var perimeterMeasureInfoWindowController: CPerimeterMeasureInfoWindowController? var areaMeasureInfoWindowController: CAreaMeasureInfoWindowController? //打印 var bookletWindowController: KMPDFBookletWindowController? var multiplePrintWindowController: KMPDFMultiplePrintWindowController? var posterPrintWindowController: KMPDFPosterPrintWindowController? var removeAllAnnotationsStore = KMPDFViewRemoveAllAnnotationsStore() private var _needSave = false var needSave: Bool { set { _needSave = newValue if (_needSave == false) { self.clearIsPDFDocumentEdited() } } get { return _needSave } } var isPDFDocumentEdited: Bool { get { return self.model.isPDFDocumentEdited } } var newMwcFlags = KMNMWCFlags(settingUpWindow: true) var searchResults: [KMSearchMode] = [] var mwcFlags: MwcFlags = MwcFlags() weak var browserWindowController: KMBrowserWindowController? //慎直接使用这个方法 var currentWindowController: NSWindowController! var savedNormalSetup: NSMutableDictionary = NSMutableDictionary() let CPDFOfficeLeftSidePaneWidthKey = "CPDFOfficeLeftSidePaneWidthKey" let CPDFOfficeRightSidePaneWidthKey = "CPDFOfficeRightSidePaneWidthKey" var extract: KMExtractImageWindowController? var pageNumber: UInt? var autoSaveTimer: Timer? private var _documentFirstLoad: Bool = true var eventMonitor: Any? var mouseRightMenuEvent: NSEvent? lazy private var homeVC: KMNHomeViewController? = { let vc = KMNHomeViewController() return vc }() fileprivate var _secureOptions: [CPDFDocumentWriteOption : Any]? var secureOptions: [CPDFDocumentWriteOption : Any]? { get { return self._secureOptions } } var documentAttribute: [CPDFDocumentAttribute : Any]? fileprivate var _removeSecureFlag = false var removeSecureFlag: Bool { get { return self._removeSecureFlag } } fileprivate var _saveWatermarkFlag = false var saveWatermarkFlag: Bool { get { return self._saveWatermarkFlag } } private var mainWindow_: NSWindow? var mainWindow: NSWindow? { get { return self.mainWindow_ } set { self.mainWindow_ = newValue } } var setDocument: CPDFDocument? { get { return document } set { if document != newValue { document = newValue } listView.document = document botaViewController?.changeDocument(document: document) } } var setPageNumber: UInt { get { return pageNumber! } set { let pageCount = listView.document?.pageCount ?? 0 var value = newValue if value > pageCount { value = pageCount } if value > 0 && listView.currentPage().pageIndex() != value-1 { listView.go(to: listView.document?.page(at: value-1)) } if pageNumber != value { pageNumber = value } } } //MARK: - func deinit { NotificationCenter.default.removeObserver(self) self.listView.delegate = nil self.listView.document?.delegate = nil self.removeEventMonitor() } override func viewDidLoad() { super.viewDidLoad() // Do view setup here. setupData() setupUI() NotificationCenter.default.addObserver(self, selector: #selector(pdfViewScrollViewDidScroll), name: NSScrollView.didLiveScrollNotification, object: listView.documentView()) NotificationCenter.default.addObserver(self, selector: #selector(pageCountChangedNotification), name: NSNotification.Name.CPDFDocumentPageCountChanged, object: listView.document) } override func viewDidAppear() { super.viewDidAppear() reloadPopUIWindow() } override func viewDidDisappear() { super.viewDidDisappear() toggleClosePopUIWindow() } override func initContentView() { super.initContentView() } override func updateUIThemeColor() { super.updateUIThemeColor() } override func updateUILanguage() { super.updateUILanguage() } //MARK: - private func setupUI() { initPDFView() initToolbar() initSideBar() setUpSplitView() } func setupData() { toolbarManager.pdfViewManager = viewManager if (UserDefaults.standard.object(forKey: CPDFViewLeftSidePaneWidthKey) != nil) { UserDefaults.standard.set(MIN_SIDE_PANE_WIDTH, forKey: CPDFViewLeftSidePaneWidthKey) UserDefaults.standard.synchronize() } newMwcFlags.settingUpWindow = true } @objc func editFontColorItemPanelAction(_ sender: Any) { if let color = (sender as? NSColorPanel)?.color { listView.changeEditingTextarea_Color(color: color) } } //MARK: - document load成功 private func documentLoadComplete() { initLeftSideController() addNotificationCenter() activityLoadMethod() let readModel = UserDefaults.standard.bool(forKey: CPDFViewIsReadModeKey) if readModel == true { self.openPDFReadMode() } reloadDigitalSigns() alertTipViewController.showInView(listView) alertTipViewController.formFieldHighlightCallback = { [weak self] in let value = CPDFKitConfig.sharedInstance().enableFormFieldHighlight() CPDFAnnotation.updateHighlightFormFiled(self?.listView, highlightFormFiled: !value) self?.toolbarManager.refreshDefaultConfigItem() } alertTipViewController.enterPasswordCallback = { [weak self] in self?.removeOwnerPassword() } alertTipViewController.digitalDetailsCallback = { [weak self] in } alertTipViewController.redactApplyCallback = { [weak self] in self?.redactApplyAction() } newMwcFlags.settingUpWindow = false loadUserDefaultsData() } private func saveAsPath() { let saveAccessCtr = KMSavePanelAccessoryController() var fileName = listView.document.documentURL.deletingPathExtension().lastPathComponent fileName = String(format: "%@_%@.pdf", fileName, "Redact") let outputSavePanel = NSSavePanel() outputSavePanel.allowedFileTypes = ["pdf"] outputSavePanel.nameFieldStringValue = fileName outputSavePanel.accessoryView = saveAccessCtr.view outputSavePanel.beginSheetModal(for: NSApp.mainWindow!) { result in if result == .OK { self.listView.document.applyRedactions() self.showProgressWindow(message: KMLocalizedString("Save") + "PDF") self.progressC?.maxValue = 3.0 self.progressC?.increment(by: 1.0) let savePDFPath = outputSavePanel.url!.path // 执行进度 [假进度] self.progressC?.increment(by: 1.0) self.progressC?.increment(by: 1.0) let isSuccess = self.listView.document.write(toFile: savePDFPath) if (isSuccess) { if (saveAccessCtr.openAutomaticButton.state == .on) { NSDocumentController.shared.km_safe_openDocument(withContentsOf: outputSavePanel.url!, display: true) { _, _, _ in } } else { let url = URL(fileURLWithPath: savePDFPath) NSWorkspace.shared.activateFileViewerSelecting([url]) } } self.hiddenProgressWindow() } } } private func reloadDigitalSigns() { let signatures = listView.document.signatures() for i in 0 ..< (signatures?.count ?? 0) { let signature:CPDFSignature = signatures?[i] ?? CPDFSignature() if signature.signers.count > 0 { signature.verifySignature(with: listView.document)//耗时,注意 } } listView.signatures = signatures } //MARK: - 活动加载相关 private func activityLoadMethod() { } private func addNotificationCenter() { NotificationCenter.default.addObserver(self, selector: #selector(annotationsAttributeHasChange), name: NSNotification.Name.CPDFListViewAnnotationsAttributeHasChange, object:nil) NotificationCenter.default.addObserver(self, selector: #selector(signatureStateChangeNoti), name: NSNotification.Name(rawValue: "CSignatureTrustCerDidChangeNotification"), object: nil) } private func loadUserDefaultsData() { applyLeftSideWidth(0, rightSideWidth: 0) //初始打开左边栏 //初始化侧边栏打开内容 if SettingsManager.sharedInstance.leftPanelType == .defaultOpen { if SettingsManager.sharedInstance.defaultOpen == .thumbnail { viewManager.pdfSideBarType = .thumbnail } else if SettingsManager.sharedInstance.defaultOpen == .outline { viewManager.pdfSideBarType = .outline } else if SettingsManager.sharedInstance.defaultOpen == .bookmark { viewManager.pdfSideBarType = .bookmark } else if SettingsManager.sharedInstance.defaultOpen == .annotation { viewManager.pdfSideBarType = .annotation } } else if SettingsManager.sharedInstance.leftPanelType == .sameAsLastOpen { if let value = UserDefaults.standard.value(forKey: "KMPDFSidebarTypeKey"), let data = value as? Int { let pdfSideBarType: KMPDFSidebarType = KMPDFSidebarType(rawValue: data) ?? .none viewManager.pdfSideBarType = pdfSideBarType } } else if SettingsManager.sharedInstance.leftPanelType == .hideLeftSide { viewManager.pdfSideBarType = .none } else if SettingsManager.sharedInstance.leftPanelType == .prioritizeOutline { } if viewManager.pdfSideBarType == .none { toggleCloseLeftSide() } else { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) { self.toggleCloseLeftSide() self.toggleOpenLeftSide(pdfSideBarType: self.viewManager.pdfSideBarType) } } //Layout & Zoom let layoutType = SettingsManager.sharedInstance.layoutType if layoutType == .singlePage { self.updatePDFViewDisplayMode(viewMode: .singlePage) } else if layoutType == .singlePageContinue { self.updatePDFViewDisplayMode(viewMode: .singlePageContinuous) } else if layoutType == .twoPage { self.updatePDFViewDisplayMode(viewMode: .twoUp) } else if layoutType == .twoPageContinue { self.updatePDFViewDisplayMode(viewMode: .twoUpContinuous) } else if layoutType == .bookMode { self.updatePDFViewDisplayMode(isbookMode: true, direction: .horizontal) } else if layoutType == .bookModeContinue { self.updatePDFViewDisplayMode(isbookMode: true, direction: .vertical) } } func refreshPDFViewZoomInfo(_ zoomType: zoomInfoType) { if zoomType == .adaptationWidth { listView.autoScales = true } else if zoomType == .adapPage { let pageHeight = listView.currentPage().size.height let pdfviewHeight = listView.bounds.size.height listView.scaleFactor = pdfviewHeight/pageHeight listView.autoScales = false } else if zoomType == .actualSize { if listView.scaleFactor != 1.0 { listView.scaleFactor = 1.0 listView.autoScales = false } } else if zoomType == .percent_10 { listView.scaleFactor = 0.1 } else if zoomType == .percent_25 { listView.scaleFactor = 0.25 } else if zoomType == .percent_50 { listView.scaleFactor = 0.5 } else if zoomType == .percent_75 { listView.scaleFactor = 0.75 } else if zoomType == .percent_100 { listView.scaleFactor = 1.0 } else if zoomType == .percent_150 { listView.scaleFactor = 1.5 } else if zoomType == .percent_200 { listView.scaleFactor = 2.0 } else if zoomType == .percent_400 { listView.scaleFactor = 4.0 } else if zoomType == .percent_800 { listView.scaleFactor = 8.0 } } func applyLeftSideWidth(_ leftSideWidth: CGFloat, rightSideWidth: CGFloat) -> Void { infoContendSplitView.setPosition(infoContendSplitView.maxPossiblePositionOfDivider(at: 1) - infoContendSplitView.dividerThickness - rightSideWidth, ofDividerAt: 1) infoContendSplitView.setPosition(leftSideWidth, ofDividerAt: 0) } //MARK: - PDFView func initPDFView() { listView.autoresizingMask = [.width, .height] listView.autoScales = true listView.delegate = self listView.pdfListViewDelegate = self listView.document = self.document listView.pageBreakMargins = NSEdgeInsetsMake(10, 0, 10, 10) listView.hideNotes = false reloadPDFSplitInfo() DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) { let zoomType = SettingsManager.sharedInstance.zoomType self.refreshPDFViewZoomInfo(zoomType) } } func updatePDFViewAnnotationMode() { let toolbarMode = viewManager.toolMode let subToolMode = viewManager.subToolMode listView.isHidden = false if toolbarMode == .None { listView.toolMode = .CTextToolMode listView.annotationType = .unkown } else if toolbarMode == .Markup { if subToolMode == .None { listView.toolMode = .CTextToolMode } else { listView.toolMode = .CNoteToolMode } //MARK: -Markup if subToolMode == .None { listView.annotationType = .unkown } else if subToolMode == .Highlight { listView.annotationType = .highlight } else if subToolMode == .Underline { listView.annotationType = .underline } else if subToolMode == .Waveline { listView.annotationType = .squiggly } else if subToolMode == .Strikethrough { listView.annotationType = .strikeOut } else if subToolMode == .Text { listView.annotationType = .freeText } else if subToolMode == .Note { listView.annotationType = .anchored } else if subToolMode == .Pen { listView.annotationType = .ink } else if subToolMode == .Eraser { listView.annotationType = .eraser } else if subToolMode == .Rectangle { listView.annotationType = .square } else if subToolMode == .Circle { listView.annotationType = .circle } else if subToolMode == .Arrow { listView.annotationType = .arrow } else if subToolMode == .Line { listView.annotationType = .line } else if subToolMode == .Measure { listView.annotationType = CPDFMeasureDefaultInfo.default_measureType() refreshMeasureInfo() } else if subToolMode == .Stamp { listView.annotationType = .stamp } else if subToolMode == .Sign { listView.annotationType = .signSignature } } else if toolbarMode == .Edit { //MARK: -编辑 if subToolMode == .None { if listView.toolMode != .CEditPDFToolMode { listView.toolMode = .CEditPDFToolMode listView.configPDFEditingInfo() } let editingPDFLoadType: CEditingLoadType = listView.editingPDFLoadType() if editingPDFLoadType.contains(.text) == false && editingPDFLoadType.contains(.image) == false { listView.setShouAddEdit([]) listView.change([.text, .image]) } } else if subToolMode == .Edit_text { if listView.toolMode != .CEditPDFToolMode { listView.toolMode = .CEditPDFToolMode listView.configPDFEditingInfo() } listView.setShouAddEdit([.text]) listView.change(.text) } else if subToolMode == .Edit_Image { if listView.toolMode != .CEditPDFToolMode { listView.toolMode = .CEditPDFToolMode listView.configPDFEditingInfo() } listView.setShouAddEdit([.image]) listView.change(.image) } else if subToolMode == .Edit_Link { listView.toolMode = .CEditLinkToolMode listView.annotationType = .link } else if subToolMode == .Edit_Crop { listView.isHidden = true listView.toolMode = .CCropToolMode } if viewManager.editType == .watermark || viewManager.editType == .background || viewManager.editType == .header_Footer || viewManager.editType == .bates { listView.isHidden = true listView.toolMode = .CTextToolMode } if subToolMode != .Edit_Crop { removeCropController() } self.showOCREditAlert() } else if toolbarMode == .Form { //MARK: -Form表单 listView.toolMode = .CFormToolMode if subToolMode == .None { listView.annotationType = .unkown } else if subToolMode == .Form_text { listView.annotationType = .textField } else if subToolMode == .Form_checkbox { listView.annotationType = .checkBox } else if subToolMode == .Form_radio { listView.annotationType = .radioButton } else if subToolMode == .Form_list { listView.annotationType = .listMenu } else if subToolMode == .Form_dropdown { listView.annotationType = .comboBox } else if subToolMode == .Form_OK { listView.annotationType = .actionButton } else if subToolMode == .Form_digitalSign { listView.annotationType = .signature } } else if toolbarMode == .Fill { //MARK: -填充 if subToolMode == .None { listView.toolMode = .CTextToolMode } else { listView.toolMode = .CNoteToolMode } if subToolMode == .None { } else if subToolMode == .Fill_tick { listView.annotationType = .signTure } else if subToolMode == .fill_fork { listView.annotationType = .signFalse } else if subToolMode == .fill_rectangle { listView.annotationType = .signCircle } else if subToolMode == .fill_line { listView.annotationType = .signLine } else if subToolMode == .fill_dot { listView.annotationType = .signDot } else if subToolMode == .fill_date { listView.annotationType = .signDate } else if subToolMode == .fill_sign { listView.annotationType = .signSignature } } else if toolbarMode == .Convert { //MARK: -转档 listView.toolMode = .CTextToolMode } else if toolbarMode == .Protect { //MARK: -Protect listView.toolMode = .CTextToolMode if subToolMode == .Redact { //密文 listView.annotationType = .redact listView.toolMode = .CRedactToolMode } else if subToolMode == .Digital_Sign { //数字签名 listView.annotationType = .digitalSign listView.toolMode = .CDigitalSignToolMode } } else if toolbarMode == .Tools { //MARK: -工具 // if subToolMode == .Tool_OCR { // listView.toolMode = .COCRToolMode // } else { // listView.toolMode = .CTextToolMode // } } if (toolbarMode != .Edit) { self.closeOCREditAlert() } } func showOrHideNotes() { self.listView.hideNotes = !self.listView.hideNotes let items = [toolbarManager.highlightProperty, toolbarManager.UnderlineProperty, toolbarManager.wavelineProperty, toolbarManager.strikethroughProperty, toolbarManager.textProperty, toolbarManager.noteProperty, toolbarManager.penProperty, toolbarManager.eraserProperty, toolbarManager.rectangleProperty, toolbarManager.circleProperty, toolbarManager.arrowProperty, toolbarManager.lineProperty, toolbarManager.measureProperty, toolbarManager.stampProperty, toolbarManager.signProperty] for item in items { item.isDisabled = listView.hideNotes } pdfToolbarController?.reloadSecondToolbar(forceRefresh: true) } //MARK: - SplitView func setUpSplitView() { infoContendSplitView.wantsLayer = true infoContendSplitView.layer?.backgroundColor = NSColor.clear.cgColor infoContendSplitView.delegate = self infoContendSplitView.layer?.masksToBounds = true } func setupSplitPDFController() { if splitPDFController == nil { splitPDFController = KMSplitPDFViewController.init() } splitPDFController?.view.frame = pdfSplitBottomView.bounds splitPDFController?.view.autoresizingMask = [.height, .width] splitPDFController?.viewManager = self.viewManager splitPDFController?.delegate = self splitPDFController?.pdfView?.pdfListViewDelegate = self splitPDFController?.reloadData() pdfSplitBottomView.addSubview(splitPDFController!.view) } //MARK: - 工具栏 func initToolbar() { toolbarBox.borderWidth = 0 if pdfToolbarController == nil { pdfToolbarController = KMPDFToolbarController.init() } pdfToolbarController?.view.frame = toolbarBox.bounds pdfToolbarController?.view.autoresizingMask = [.width, .height] pdfToolbarController?.delegate = self toolbarBox.contentView = pdfToolbarController?.view pdfToolbarController?.viewManager = viewManager pdfToolbarController?.toolbarManager = toolbarManager pdfToolbarController?.pdfView = listView pdfToolbarController?.setUpData() refreshToolbarViewHeightInfo() if listView.showFormFieldName { toolbarManager.form_ShowName_Property.righticon = NSImage(named: "tick_Green") } else { toolbarManager.form_ShowName_Property.righticon = nil } DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.15) { self.pdfToolbarController?.clickWithIdentify(KMPDFToolbar_Markup_Identifier) } } func refreshToolbarViewHeightInfo() { let _viewManager = viewManager if viewManager.isPageEditMode { toolbarBoxHeightConst.constant = 80 } else if viewManager.editType == .watermark || viewManager.editType == .background || viewManager.editType == .header_Footer || viewManager.editType == .bates { toolbarBoxHeightConst.constant = 40 } else if _viewManager.toolMode == .Markup || _viewManager.toolMode == .Edit || _viewManager.toolMode == .Form || _viewManager.toolMode == .Fill || _viewManager.toolMode == .Convert || _viewManager.toolMode == .Protect || _viewManager.toolMode == .Tools { toolbarBoxHeightConst.constant = 80 if _viewManager.subToolMode == .Redact { toolbarBoxHeightConst.constant = 40 } } else { toolbarBoxHeightConst.constant = 40 } } func toolbarViewModeChanged() { updatePDFViewAnnotationMode() refreshToolbarRightViewInfo() if viewManager.toolMode != .Edit && viewManager.subToolMode != .Edit_Crop { removeCropController() } } //MARK: - 右边属性栏 func refreshToolbarRightViewInfo() { //统一刷新viewManager.showRightSide, 由这个参数控制右边属性边框的展开与隐藏 if viewManager.showRightSide == true { toolbarManager.rightViewProperty.state = .pressed toggleOpenRightSide() rightSideController?.reloadDataWithPDFView(pdfView: listView) } else { toggleCloseRightSide() } if viewManager.showRightSide == true { toolbarManager.rightViewProperty.state = .pressed } else { toolbarManager.rightViewProperty.state = .normal } pdfToolbarController?.reloadRightToolsView() } //MARK: - 侧边工具栏 func initSideBar() { sidebarBox.borderWidth = 0 if sideBarController == nil { sideBarController = KMPDFSideBarController.init() } sideBarController?.view.frame = sidebarBox.bounds sideBarController?.view.autoresizingMask = [.width, .height] sidebarBox.contentView = sideBarController?.view sideBarController?.pdfView = listView sideBarController?.delegate = self sideBarController?.pdfViewManager = viewManager sideBarController?.reloadData() } func reloadSideBar() { sideBarController?.reloadData() if viewManager.editType == .none { sideBarController?.searchItem.isHidden = false sideBarController?.thumbnailItem.isHidden = false sideBarController?.outlineItem.isHidden = false sideBarController?.bookmarkItem.isHidden = false sideBarController?.annotationItem.isHidden = false sideBarController?.aiToolItem.isHidden = false } else { sideBarController?.searchItem.isHidden = true sideBarController?.thumbnailItem.isHidden = true sideBarController?.outlineItem.isHidden = true sideBarController?.bookmarkItem.isHidden = true sideBarController?.annotationItem.isHidden = true sideBarController?.aiToolItem.isHidden = true } } //MARK: - 左边侧边栏 func initLeftSideController() { if botaViewController == nil { botaViewController = KMNLeftSideViewController(listView.document) } botaViewController?.leftSideViewDelegate = self botaViewController?.view.frame = infoSplitLeftView.bounds botaViewController?.view.autoresizingMask = [.width, .height] if botaViewController != nil { infoSplitLeftView?.addSubview(botaViewController!.view) } } private func leftSidePaneIsOpen() -> Bool { return !infoContendSplitView.isSubviewCollapsed(infoSplitLeftView) //第一次点击时存在问题,待解决 } func toggleOpenLeftSide(pdfSideBarType: KMPDFSidebarType) { if(leftSidePaneIsOpen() == false) { let leftWidthNumber = UserDefaults.standard.object(forKey: CPDFViewLeftSidePaneWidthKey) as? NSNumber ?? MIN_SIDE_PANE_WIDTH infoContendSplitView.setPosition(MIN_SIDE_PANE_WIDTH.doubleValue, ofDividerAt: 0) //暂时无法记录上一次打开的宽度 } if pdfSideBarType == .search { botaViewController?.searchViewC.handdler.pdfView = listView botaViewController?.leftsideType = .search } else if pdfSideBarType == .thumbnail { botaViewController?.leftsideType = pdfSideBarType botaViewController?.thumnailViewController?.reloadDatas() botaViewController?.currentPageDidChangedAction(listView: listView) } else if pdfSideBarType == .outline { botaViewController?.outlineViewC.handdler.pdfView = listView botaViewController?.leftsideType = pdfSideBarType } else if pdfSideBarType == .bookmark { botaViewController?.bookmarkViewC.handdler.pdfView = listView botaViewController?.leftsideType = pdfSideBarType } else if pdfSideBarType == .annotation { botaViewController?.annoController.listView = listView botaViewController?.leftsideType = .annotation } else if pdfSideBarType == .aiTools { botaViewController?.leftsideType = .aiTools } } func toggleCloseLeftSide() { if(leftSidePaneIsOpen() == true) { infoContendSplitView.setPosition(0, ofDividerAt: 0) } } //MARK: - 右侧属性栏 func initRightSideController() { if rightSideController == nil { rightSideController = KMRightSideController.init() rightSideController?.delegate = self } rightSideController?.view.frame = CGRectMake(0, 0, MIN_SIDE_PANE_WIDTH.doubleValue, 680) rightSideController?.view.autoresizingMask = [.height, .maxXMargin] } func removeRightSideController() { rightSideController?.view.removeFromSuperview() rightSideController = nil } @objc func toggleOpenRightSide() -> Void { if rightSideController != nil { return } initRightSideController() rightSideController?.view.frame = infoSplitRightView.bounds rightSideController?.view.autoresizingMask = [.width, .height] infoSplitRightView.addSubview(rightSideController!.view) infoContendSplitView.setPosition(CGRectGetWidth(view.frame)-MIN_SIDE_PANE_WIDTH.doubleValue, ofDividerAt: 1) rightSideController?.viewManager = self.viewManager rightSideController?.reloadDataWithPDFView(pdfView: listView) } @objc func toggleCloseRightSide() -> Void { removeRightSideController() infoContendSplitView.setPosition(CGRectGetWidth(view.frame), ofDividerAt: 1) } func refreshRightSide() -> Void { if let rightVC = rightSideController, let _ = rightSideController?.view.superview { rightVC.reloadDataWithPDFView(pdfView: listView) } } //MARK: - PDFDisplayView func updatePDFDisplaySettingView() { if viewManager.showDisplayView { infoSplitViewLeftConst.constant = 0 infoContendSplitView.setPosition(MIN_SIDE_PANE_WIDTH.doubleValue, ofDividerAt: 0) } else { infoSplitViewLeftConst.constant = 44 if viewManager.pdfSideBarType == .none { toggleCloseLeftSide() } else { toggleOpenLeftSide(pdfSideBarType: viewManager.pdfSideBarType) } } if viewManager.showDisplayView { if displaySettingController == nil { displaySettingController = KMNDisplayViewController.init() } displaySettingController?.view.frame = CGRectMake(0, 0, MIN_SIDE_PANE_WIDTH.doubleValue, CGRectGetHeight(bottomContendBox.frame)) displaySettingController?.view.autoresizingMask = [.height, .width] infoSplitLeftView.addSubview(displaySettingController!.view) displaySettingController?.pdfView = self.listView displaySettingController?.viewManager = self.viewManager displaySettingController?.delegate = self displaySettingController?.reloadData() } else { displaySettingController?.view.removeFromSuperview() displaySettingController = nil } } //MARK: - 页面编辑 func enterPageEditMode() { pageEditViewController = KMNPageEditViewController(self.document) if(pageEditViewController != nil) { bottomContendBox.addSubview(pageEditViewController!.view) pageEditViewController?.view.frame = bottomContendBox.bounds pageEditViewController?.thumbnailBaseViewDelegate = self pageEditViewController?.selectionIndexPaths = [IndexPath(item: listView.currentPageIndex, section: 0)] pageEditViewController?.view.autoresizingMask = [.width,.height] pageEditViewController?.currentUndoManager = listView.undoManager toolbarManager.page_pageInfo_Property.text = String(listView.currentPageIndex + 1) pdfToolbarController?.refreshSecondToolbarItemsState() listView.isHidden = true } } func exitPageEditMode() { if pageEditViewController != nil { pageEditViewController?.view.removeFromSuperview() pageEditViewController = nil } listView.isHidden = false if listView.document?.isModified() == true { listView.layoutDocumentView() botaViewController?.thumnailViewController?.reloadDatas() botaViewController?.annoController.note_reloadDataIfNeed() } } //MARK: - 阅读模式 func openPDFReadMode() { if viewManager.showDisplayView { UserDefaults.setDefaultBoolValue(true, toKey: "ShowDisplayViewWhenExitPDFReadMode") viewManager.showDisplayView = false pdfToolbarController?.reloadLeftIconView() updatePDFDisplaySettingView() } infoSplitViewLeftConst.constant = 0 toolbarBoxHeightConst.constant = 0 view.window?.makeFirstResponder(listView) let readModeMessage: ComponentMessage = ComponentMessage() readModeMessage.properties = ComponentMessageProperty(messageType: .normal_custom, title: KMLocalizedString("Read Mode On")) readModeMessage.frame = CGRectMake((CGRectGetWidth(self.view.frame) - readModeMessage.properties.propertyInfo.viewWidth)/2, CGRectGetHeight(self.view.frame) - readModeMessage.properties.propertyInfo.viewHeight - 8, readModeMessage.properties.propertyInfo.viewWidth, readModeMessage.properties.propertyInfo.viewHeight) readModeMessage.reloadData() readModeMessage.show(inView: self.view, autoHideSeconde: 2) setUpPDFPageNumberToolbar() } func exitPDFReadMode() { viewManager.isPDFReadMode = false if UserDefaults.getDefaultBoolValue(forKey: "ShowDisplayViewWhenExitPDFReadMode") == true { if viewManager.showDisplayView == false { viewManager.showDisplayView = true pdfToolbarController?.reloadLeftIconView() } UserDefaults.setDefaultBoolValue(false, toKey: "ShowDisplayViewWhenExitPDFReadMode") } updatePDFDisplaySettingView() refreshToolbarViewHeightInfo() reloadPDFPageNumberToolbar() DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { let readModeMessage: ComponentMessage = ComponentMessage() readModeMessage.properties = ComponentMessageProperty(messageType: .normal_custom, title: KMLocalizedString("Read Mode Off")) readModeMessage.frame = CGRectMake((CGRectGetWidth(self.infoSplitCenterView.frame) - readModeMessage.properties.propertyInfo.viewWidth)/2, CGRectGetHeight(self.infoSplitCenterView.frame) - readModeMessage.properties.propertyInfo.viewHeight - 8, readModeMessage.properties.propertyInfo.viewWidth, readModeMessage.properties.propertyInfo.viewHeight) readModeMessage.reloadData() readModeMessage.show(inView: self.infoSplitCenterView, autoHideSeconde: 2) } } //MARK: - PPT func togglePresentation(_ sender: Any?) { if self.canExitPresentation() { exitFullScreen() } else if self.canEnterPresentation() { NotificationCenter.default.addObserver(self, selector: #selector(willEnterInteractionModeNotification), name: NSWindow.willEnterInteractionModeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didEnterInteractionModeNotification), name: NSWindow.didEnterInteractionModeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(willShowFullScreenNotification), name: NSWindow.willShowFullScreenNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didShowFullScreenNotification), name: NSWindow.didShowFullScreenNotification, object: nil) view.window?.enterPresentation(provider: self) } } 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) 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) } func exitPresentationMode() { NotificationCenter.default.removeObserver(self, name: NSWindow.willEnterInteractionModeNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSWindow.didEnterInteractionModeNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSWindow.willShowFullScreenNotification, object: nil) NotificationCenter.default.removeObserver(self, name: NSWindow.willShowFullScreenNotification, object: nil) } func exitFullScreen() { if self.canExitPresentation() == true { let mainDocument = self.myDocument as? KMMainDocument let browserWindowController = mainDocument?.browser?.windowController as? KMBrowserWindowController browserWindowController?.exitFullscreen() } } func exitFullscreenMode() { if self.interactionMode == .presentation { self.exitPresentationMode() } self.applyPDFSettings(self.savedNormalSetup) self.savedNormalSetup.removeAllObjects() listView.layoutDocumentView() listView.requiresDisplay() if let backgroundColor = UserDefaults.standard.color(forKey: KMBackgroundColorKey) { listView.backgroundColor = backgroundColor } reloadPDFSplitInfo() } 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.layoutDocumentView() } 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 } 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 fadeOutFullScreenWindow() { guard let fullScreenWindow = self.view.window as? KMFullScreenWindow else { NSSound.beep() return } let mainWindow = fullScreenWindow.interactionParent let collectionBehavior = mainWindow?.collectionBehavior mainWindow?.alphaValue = 0 if let data = mainWindow?.responds(to: NSSelectorFromString("setAnimationBehavior:")), data { mainWindow?.animationBehavior = .none } // trick to make sure the main window shows up in the same space as the fullscreen window fullScreenWindow.addChildWindow(mainWindow!, ordered: .below) fullScreenWindow.removeChildWindow(mainWindow!) fullScreenWindow.level = .popUpMenu // these can change due to the child window trick mainWindow?.level = .normal mainWindow?.alphaValue = 1.0 mainWindow?.collectionBehavior = collectionBehavior! mainWindow?.display() mainWindow?.makeFirstResponder(self.listView) mainWindow?.recalculateKeyViewLoop() // mainWindow?.delegate = self mainWindow?.makeKey() if let data = mainWindow?.responds(to: NSSelectorFromString("setAnimationBehavior:")), data { mainWindow?.animationBehavior = .default } NSApp.removeWindowsItem(fullScreenWindow) fullScreenWindow.fadeOut() } //MARK: - PDF分屏视图 func reloadPDFSplitInfo() { if listView.viewSplitMode == .disable { pdfSplitView.isHidden = true listView.frame = infoSplitCenterView.bounds infoSplitCenterView.addSubview(listView) if splitPDFController != nil { splitPDFController = nil } } else { pdfSplitView.isHidden = false listView.frame = pdfSplitTopView.bounds pdfSplitTopView.addSubview(listView) setUpPDFPageNumberToolbar() setupSplitPDFController() if listView.viewSplitMode == .horizontal { pdfSplitView.isVertical = false } else if listView.viewSplitMode == .vertical { pdfSplitView.isVertical = true } } } func setUpPDFPageNumberToolbar() { if pageNumberToolbar != nil { pageNumberToolbar?.removeFromSuperview() pageNumberToolbar = nil } if pageNumberToolbar == nil { pageNumberToolbar = KMPageNumberPromptView.init() } pageNumberToolbar?.frame = CGRectMake(CGRectGetWidth(listView.frame)/2-144, 20, 288, 40) pageNumberToolbar?.autoresizingMask = [.minXMargin, .maxXMargin, .maxYMargin] pageNumberToolbar?.pdfView = self.listView pageNumberToolbar?.reloadData() pageNumberToolbar?.isHidden = true listView.addSubview(pageNumberToolbar!) reloadPDFPageNumberToolbar() } func reloadPDFPageNumberToolbar() { if viewManager.isPDFReadMode == true || (viewManager.splitShowBottomBar && listView.viewSplitMode != .disable) { pageNumberToolbar?.isHidden = false pageNumberToolbar?.reloadData() } else { pageNumberToolbar?.isHidden = true } } //MARK: - Edit模式 func showEditToolbarView() { if editToolbarView == nil { editToolbarView = KMEditToolbarView() } editToolbarView?.frame = toolbarBox.bounds editToolbarView?.delegate = self editToolbarView?.autoresizingMask = [.width, .height] toolbarBox.contentView = editToolbarView reloadSideBar() } func exitEditToolbarView() { viewManager.editType = .none viewManager.subToolMode = .None editToolbarView?.removeFromSuperview() editToolbarView = nil watermarkViewController?.view.removeFromSuperview() watermarkViewController = nil backgroundViewController?.view.removeFromSuperview() backgroundViewController = nil headerFooterViewController?.view.removeFromSuperview() headerFooterViewController = nil batesViewController?.view.removeFromSuperview() batesViewController = nil refreshToolbarViewHeightInfo() toolbarBox.contentView = pdfToolbarController?.view updatePDFViewAnnotationMode() reloadSideBar() } func updateEditModeDocumentWhenPageChanged() { if viewManager.editType == .watermark { updateWatermarkDocument() } else if viewManager.editType == .background { updateBackgroundDocument() } else if viewManager.editType == .header_Footer { updateHeaderFooterDocument() } else if viewManager.editType == .bates { updateBatesDocument() } else if viewManager.subToolMode == .Edit_Crop { updateCropDocument() } } //MARK: - 数字签名 func writeSignatureToWidget(_ widget: CPDFSignatureWidgetAnnotation, _ path: String, _ password: String, _ config: CPDFSignatureConfig, _ isLock: Bool) ->() { let fileName = listView.document.documentURL?.lastPathComponent let fileNameWithoutExtension = URL(fileURLWithPath: fileName!).deletingPathExtension().lastPathComponent let outputSavePanel = NSSavePanel() outputSavePanel.directoryURL = listView.document.documentURL.deletingLastPathComponent() outputSavePanel.title = NSLocalizedString("", comment: "Save as PDF") outputSavePanel.allowedFileTypes = ["pdf"] outputSavePanel.nameFieldStringValue = fileNameWithoutExtension + "_" + NSLocalizedString("Signed", comment: "") let result = outputSavePanel.runModal() if result == .OK { let contentArr = NSMutableArray() var locationStr = "" var reasonStr = NSLocalizedString("none", comment: "") for item in config.contents { if item.key == NSLocalizedString("Reason", comment: "") { if item.value == NSLocalizedString("", comment: "") { item.value = " " + NSLocalizedString("none", comment: "") } reasonStr = item.value } else if item.key == NSLocalizedString("Location", comment: "") { if item.value == NSLocalizedString("", comment: "") { item.value = " " } locationStr = item.value } contentArr.add(item) } config.contents = contentArr as? [CPDFSignatureConfigItem] widget.setFieldName(widget.getValidName(inPage: widget.page)) widget.signAppearanceConfig(config) let success = listView.document.writeSignature(to: outputSavePanel.url, withWidget: widget, pkcs12Cert: path, password: password, location: locationStr, reason: reasonStr, permissions: .forbidChange) widget.removeSignature() if success { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { NSDocumentController.shared.openDocument(withContentsOf: outputSavePanel.url!, display: true) { document, documentWasAlreadyOpen, error in if error != nil { NSApp.presentError(error!) return } } } } else { let alert = NSAlert.init() alert.messageText = NSLocalizedString("Save failed!", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() } widget.page.removeAnnotation(widget) listView.setNeedsDisplayAnnotationViewFor(widget.page) } else { widget.page.removeAnnotation(widget) listView.setNeedsDisplayAnnotationViewFor(widget.page) } } func popUpSignatureWidgetState(_ signature: CPDFSignature, _ pdfListView: CPDFListView) ->(){ signaturestateVC.signature = signature signaturestateVC.pdfListView = pdfListView signaturestateVC.actionBlock = { [weak self, weak signaturestateVC] stateVCSelf, actionType in guard let weakSelf = self, let stateVC = signaturestateVC else { return } if actionType == .cancel { stateVC.dismiss(stateVCSelf) } else if actionType == .confirm { if let signer = signature.signers.first, let data = signer.certificates { let signatureDetail = DSignatureDetailsViewController.init() signatureDetail.certificates = data signatureDetail.signature = signature signatureDetail.pdfListView = pdfListView stateVCSelf.presentAsSheet(signatureDetail) } else { NSSound.beep() } } } self.presentAsSheet(signaturestateVC) signaturestateVC.reloadData() } // MARK: - 显示合并窗口 public func showMergeWindow(url: URL? = nil, _ password: String?) { DispatchQueue.main.async { var documentURL = url if documentURL == nil { documentURL = self.listView.document?.documentURL } guard let _url = documentURL else { return } guard let document = PDFDocument(url: _url) else { return } self.mergeWindowController = KMMergeWindowController(document: document, password: password ?? "") self.mergeWindowController!.oriDucumentUrl = self.listView.document?.documentURL self.mergeWindowController!.pageIndex = self.listView.currentPageIndex self.mergeWindowController!.cancelAction = { [unowned self] controller in self.view.window?.endSheet(mergeWindowController!.window!) } self.mergeWindowController!.mergeAction = { [unowned self] controller, filePath in self.view.window?.endSheet(mergeWindowController!.window!) } self.view.window?.beginSheet(self.mergeWindowController!.window!) } } //MARK: - Crop裁剪 func showCropController() { if cropController == nil { cropController = KMCropController.init() cropController?.view.frame = infoSplitCenterView.bounds cropController?.view.autoresizingMask = [.width, .height] cropController?.delegate = self infoSplitCenterView.addSubview(cropController!.view) updateCropDocument() if viewManager.showRightSide == false { viewManager.showRightSide = true refreshToolbarRightViewInfo() } } } func updateCropDocument() { guard let controller = cropController else { return } controller.pdfDocument = nil let page = listView.document.page(at: UInt(listView.currentPageIndex)) let editDocument = CPDFDocument.init() editDocument?.insertPageObject(page, at: 0) if let editPage = editDocument?.page(at: 0) { editPage.setBounds(CGRectMake(0, 0, editPage.bounds(for: .mediaBox).size.width, editPage.bounds(for: .mediaBox).size.height), for: .cropBox) controller.selectionRect = page?.bounds(for: .cropBox) ?? .zero } controller.pdfDocument = editDocument controller.reloadData() } func removeCropController() { if cropController != nil { cropController?.view.removeFromSuperview() cropController = nil toolbarManager.edit_crop_Property.state = .normal } } // MARK: - Secure 【安全】 public func hiddenSecureLimitTip() { } func savePageNumberIfNeed() { let scaleFactor = self.listView.scaleFactor ?? 0 if scaleFactor <= 0 { return } if self.listView.document != nil { KMPreferenceManager.shared.setPageNumber(self.listView.currentPageIndex, forKey: self.listView.document.documentURL.path) KMPreferenceManager.shared.setPageScale(Float(self.listView.scaleFactor), forKey: self.listView.document.documentURL.path) } } // MARK: - 显示加密弹窗 public func showSecureWindow() { guard let url = self.listView.document?.documentURL else { return } self.securityWindowController = KMSecurityWindowController(windowNibName: "KMSecurityWindowController") guard let securityWindowController = securityWindowController else { return } securityWindowController.documentURL = self.listView.document?.documentURL securityWindowController.batchAction = { [unowned self] controller, files in self.view.window?.endSheet((securityWindowController.window)!) let batchWindowController = KMBatchOperateWindowController.sharedWindowController let batchOperateFile = KMBatchOperateFile(filePath: self.document?.documentURL.path ?? "", type: .AddPassword) batchWindowController.switchToOperateType(.AddPassword, files: [batchOperateFile]) batchWindowController.window?.makeKeyAndOrderFront("") } securityWindowController.doneAction = { [unowned self] controller, options, attribute in let openPanel = NSOpenPanel() openPanel.canChooseFiles = false openPanel.canChooseDirectories = true openPanel.canCreateDirectories = true openPanel.beginSheetModal(for: NSWindow.currentWindow()) { (result) in if result == NSApplication.ModalResponse.OK { for fileURL in openPanel.urls { let document = CPDFDocument(url: self.document?.documentURL) if document != nil { document!.setDocumentAttributes(attribute) let path = fileURL.path.stringByAppendingPathComponent(url.deletingPathExtension().lastPathComponent) + "_SetPassword" + "." + url.pathExtension let success = document!.write(to: NSURL(fileURLWithPath: path) as URL, withOptions: options) if success { self.view.window?.endSheet((securityWindowController.window)!) NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: path)]) } } } } } } securityWindowController.cancelAction = { [unowned self] controller in self.view.window?.endSheet((securityWindowController.window)!) } NSWindow.currentWindow().beginSheet(securityWindowController.window!) } // MARK: - 移除文档密码 public func showRemoveSecureWindow() { var isDocumentLocked: Bool = false if self.document?.allowsCopying == false || self.document?.allowsPrinting == false { isDocumentLocked = true } else if (self.document?.password ?? "").count > 0 { isDocumentLocked = true } if isDocumentLocked == false { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = KMLocalizedString("This document doesn’t contain any security settings and doesn‘t need to be removed.") alert.addButton(withTitle: KMLocalizedString("OK")) alert.beginSheetModal(for: NSWindow.currentWindow()) { returnCode in } } 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 var array: [URL] = [] for item in files { array.append(NSURL(fileURLWithPath: item.filePath) as URL) } self.showBatchWindow(type: .batchRemove, files: array) } 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 savePanel = NSSavePanel() savePanel.nameFieldStringValue = self.listView.document.documentURL.deletingPathExtension().lastPathComponent + "_RemovePassword" savePanel.allowedFileTypes = ["pdf"] 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() NSWorkspace.shared.activateFileViewerSelecting([savePanel.url!]) } else { self.hiddenSecureLimitTip() } } } } } NSWindow.currentWindow().beginSheet(controller.window!) } } //MARK: - Unlock Document func unlockPDFDocument() { KMBaseWindowController.checkPassword(url: self.document!.documentURL!, type: .owner, password: self.document?.password ?? "") { [unowned self] success, resultPassword in self.listView.document.unlock(withPassword: resultPassword) } } //MARK: - Watermark水印 func showWatermarkController() { viewManager.editType = .watermark showEditToolbarView() editToolbarView?.editType = .watermark if KMWatermarkManager.defaultManager.watermarks.count == 0 { editToolbarView?.editSubType = .add } else { editToolbarView?.editSubType = .template } editToolbarView?.reloadData() if watermarkViewController == nil { watermarkViewController = KMWatermarkController.init() } watermarkViewController?.view.frame = CGRectMake(44, 0, CGRectGetWidth(bottomContendBox.frame)-44, CGRectGetHeight(bottomContendBox.frame)) watermarkViewController?.view.autoresizingMask = [.maxXMargin, .width, .height] watermarkViewController?.delegate = self bottomContendBox.contentView?.addSubview(watermarkViewController!.view) watermarkViewController?.editSubType = editToolbarView?.editSubType ?? .template updateWatermarkDocument() } func updateWatermarkDocument() { guard let controller = watermarkViewController else { return } var editDocument = CPDFDocument.init() if let vcDoc = controller.pdfDocument { editDocument = vcDoc } let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) if editDocument?.pageCount == 2 { let theIndex = IndexSet(integer: 1) editDocument?.removePage(at: theIndex) } if watermarkViewController?.pdfDocument == nil { watermarkViewController?.pdfDocument = editDocument } watermarkViewController?.resetUI() watermarkViewController?.reloadData() } //移除文档水印 func removePDFWatermark() { 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.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) { for watermark in watermarks! { listView.document.removeWatermark(watermark) } listView.layoutDocumentView() _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Watermark removed"), type: .success, fromView: bottomContendBox, point:CGPointMake(CGRectGetWidth(bottomContendBox.frame)/2, CGRectGetHeight(bottomContendBox.frame)-28)) } } func batchAddWatermark() { self.showBatchWindow(type: .watermark, files: nil) } func batchRemoveWatermark() { self.showBatchWindow(type: .batchRemove, files: nil) } //MARK: - PopUI func reloadPopUIWindow() { if listView.toolMode == .CSelectToolMode { let pageRect = listView.currentSelectionRect() let page:CPDFPage? = listView.currentSelectionPage() if listView.selectionRect != CGRectZero && page != nil { let positioningRect = listView.convert(pageRect, from: page) if (CGRectIntersectsRect(positioningRect, listView.frame)) { reloadPopUIOperation() return } } toggleClosePopUIWindow() } else if listView.toolMode == .COCRToolMode { let pageRect = listView.currentSelectionRect() let page:CPDFPage? = listView.currentSelectionPage() if listView.selectionRect != CGRectZero && page != nil { let positioningRect = listView.convert(pageRect, from: page) if (CGRectIntersectsRect(positioningRect, listView.frame)) { reloadPopUIOperation() return } } toggleClosePopUIWindow() } else if(listView.isEditing() == false) { let activeAnnotations:[CPDFAnnotation] = listView.activeAnnotations as! [CPDFAnnotation] if(activeAnnotations.count > 0) { if let page = activeAnnotations.first?.page { let pageRect = listView.selectionMultipleBounds(with: activeAnnotations) let positioningRect = listView.convert(pageRect, from: page) if (CGRectIntersectsRect(positioningRect, listView.frame)) { reloadPopUIActiveAnnotations(activeAnnotations: activeAnnotations) } else { toggleClosePopUIWindow() } } else { toggleClosePopUIWindow() } } else { toggleClosePopUIWindow() } if(listView.popOver?.isShown == true || (groupListMenuGroup?.superview) != nil) { //右键菜单弹出时,或者Pop编辑框弹出时不显示Pop toggleClosePopUIWindow() } } else { let editAreas:[CPDFEditArea] = listView.km_EditingAreas() if(editAreas.count > 0) { if let page = editAreas.first?.page { let pageRect = listView.selectionMultipleBounds(withEditArea: editAreas) let positioningRect = listView.convert(pageRect, from: page) if (CGRectIntersectsRect(positioningRect, listView.frame)) { reloadPopUIContentEdits(editAreas: editAreas) } else { toggleClosePopUIWindow() } } else { toggleClosePopUIWindow() } } else { toggleClosePopUIWindow() } if(listView.popOver?.isShown == true || (groupListMenuGroup?.superview) != nil) { //右键菜单弹出时,或者Pop编辑框弹出时不显示Pop toggleClosePopUIWindow() } } } func toggleClosePopUIWindow() { let popWindow = KMNPopAnnotationWindowController.shared if popWindow.window?.isVisible == true { closeAnnotationPopWindow() } let editPopWindow = KMNPopContentEditWindowController.shared if editPopWindow.window?.isVisible == true { closePopContentEditWindow() } let operationWindow = KMNPopOperationWindowController.shared if operationWindow.window?.isVisible == true { closePopOperationWindow() } } func closeAnnotationPopWindow() { KMNPopAnnotationWindowController.shared.closeWindow(listView: listView) } func closePopContentEditWindow() { KMNPopContentEditWindowController.shared.closeWindow(listView: listView) } func closePopOperationWindow() { KMNPopOperationWindowController.shared.closeWindow(listView: listView) } func reloadPopUIOperation() { if listView.selectionRect != CGRectZero { let popWindow = KMNPopOperationWindowController.shared if popWindow.window?.isVisible == false { listView.window?.addChildWindow(popWindow.window ?? NSWindow(), ordered: .above) } popWindow.listView = listView if listView.toolMode == .CSelectToolMode { popWindow.popType = .crop popWindow.cropCurrentCallback = {[weak self] in let rect = self?.listView.currentSelectionRect() ?? CGRect.zero let orgPage : CPDFPage = self?.listView.currentSelectionPage() ?? CPDFPage() self?.cropPages(atIndexs: [orgPage.pageIndex()], to: [rect]) self?.closePopOperationWindow() } } else if listView.toolMode == .COCRToolMode { popWindow.popType = .ocr popWindow.OCRAction = { [weak self] in self?.convertSelectionRectOCR(rect: self?.listView.currentSelectionRect() ?? CGRectZero) } } popWindow.updatePDFViewCallback = {[weak self] in self?.closePopOperationWindow() self?.listView.setNeedsDisplayForVisiblePages() } updatePopOperationPopWinodwFrame() } else { closePopOperationWindow() } } func reloadPopUIActiveAnnotations(activeAnnotations:[CPDFAnnotation]) { let annotationMode = KMNAnnotationPopMode(pdfAnnotations: activeAnnotations ) let popWindow = KMNPopAnnotationWindowController.shared if annotationMode.popType == .popTypeNone { closeAnnotationPopWindow() } else { if popWindow.window?.isVisible == false { listView.window?.addChildWindow(popWindow.window ?? NSWindow(), ordered: .above) } popWindow.listView = listView popWindow.annotationPopMode = annotationMode popWindow.isOpenPane = viewManager.showRightSide updateAnnotationsPopWinodwFrame() popWindow.updatePDFViewCallback = {[weak self] in self?.rightSideController?.reloadDataWithPDFView(pdfView: self?.listView ?? CPDFListView()) self?.listView.setNeedsDisplayMultiAnnotations(annotationMode.annotations) } popWindow.paneCallback = {[weak self] isOpen in if isOpen == true { self?.viewManager.showRightSide = true } else { self?.viewManager.showRightSide = false } self?.refreshToolbarRightViewInfo() } } } func reloadPopUIContentEdits(editAreas:[CPDFEditArea]) { let editingAreas = listView.km_EditingAreas() let editMode = KMNEditContentPopMode(currentEditAreas: editingAreas) let popWindow = KMNPopContentEditWindowController.shared if editMode.popType == .editNone { closePopContentEditWindow() } else { listView.window?.addChildWindow(popWindow.window ?? NSWindow(), ordered: .above) popWindow.listView = listView popWindow.editContentPopMode = editMode popWindow.isOpenPane = viewManager.showRightSide updateContentEditPopWinodwFrame() popWindow.paneCallback = {[weak self] isOpen in if isOpen == true && self?.viewManager.showRightSide == false { self?.viewManager.showRightSide = false } else { self?.viewManager.showRightSide = true } self?.refreshToolbarRightViewInfo() } } } func updateAnnotationsPopWinodwFrame() { let popWindow = KMNPopAnnotationWindowController.shared if popWindow.window?.isVisible == true { popWindow.updateFrame(listView: listView) } } func updateContentEditPopWinodwFrame() { let popWindow = KMNPopContentEditWindowController.shared if popWindow.window?.isVisible == true { popWindow.updateFrame(listView: listView) } } func updatePopOperationPopWinodwFrame() { let popWindow = KMNPopOperationWindowController.shared if popWindow.window?.isVisible == true { popWindow.updateFrame(listView: listView,page: listView.currentSelectionPage()) } } //MARK: - 安全 func removeOwnerPassword() { guard let doc = listView.document else { NSSound.beep() return } if doc.permissionsStatus != .user { NSSound.beep() return } _ = KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: doc.documentURL) { [weak self] result, password in if result == .cancel { /// 关闭 return } self?.listView.document?.unlock(withPassword: password) if doc.permissionsStatus == .owner { self?.alertTipViewController.reloadSecureAlertUI() self?.alertTipViewController.reloadAlertUIFrame() } } } //MARK: - Background背景 func showBackgroundController() { viewManager.editType = .background showEditToolbarView() editToolbarView?.editType = .background if KMBackgroundManager.defaultManager.datas.count == 0 { editToolbarView?.editSubType = .add } else { editToolbarView?.editSubType = .template } editToolbarView?.reloadData() if backgroundViewController == nil { backgroundViewController = KMBackgroundController.init() } backgroundViewController?.view.frame = CGRectMake(44, 0, CGRectGetWidth(bottomContendBox.frame)-44, CGRectGetHeight(bottomContendBox.frame)) backgroundViewController?.view.autoresizingMask = [.maxXMargin, .width, .height] backgroundViewController?.delegate = self bottomContendBox.contentView?.addSubview(backgroundViewController!.view) backgroundViewController?.editSubType = editToolbarView?.editSubType ?? .template backgroundViewController?.resetUI() updateBackgroundDocument() } func updateBackgroundDocument() { guard let controller = backgroundViewController else { return } controller.pdfDocument = nil let editDocument = CPDFDocument.init() let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) backgroundViewController?.pdfDocument = editDocument backgroundViewController?.reloadData() } func removePDFBackground() { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Are you sure you want to remove the background?", comment: "") alert.addButton(withTitle: NSLocalizedString("Delete", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result == .alertFirstButtonReturn) { let background = listView.document.background() background?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Background removed"), type: .success, fromView: bottomContendBox, point:CGPointMake(CGRectGetWidth(bottomContendBox.frame)/2, CGRectGetHeight(bottomContendBox.frame)-28)) } } func batchAddBackground() { self.showBatchWindow(type: .background, files: nil) } func batchRemoveBackground() { self.showBatchWindow(type: .batchRemove, files: nil) } //MARK: - header&footer func showHeaderFooterController() { viewManager.editType = .header_Footer showEditToolbarView() editToolbarView?.editType = .header_Footer if KMHeaderFooterManager.defaultManager.headFooterObjects.count == 0 { editToolbarView?.editSubType = .add } else { editToolbarView?.editSubType = .template } editToolbarView?.reloadData() if headerFooterViewController == nil { headerFooterViewController = KMHeaderFooterController.init() } headerFooterViewController?.view.frame = CGRectMake(44, 0, CGRectGetWidth(bottomContendBox.frame)-44, CGRectGetHeight(bottomContendBox.frame)) headerFooterViewController?.view.autoresizingMask = [.maxXMargin, .width, .height] headerFooterViewController?.totalPDFCount = Int(listView.document.pageCount) headerFooterViewController?.delegate = self bottomContendBox.contentView?.addSubview(headerFooterViewController!.view) headerFooterViewController?.editSubType = editToolbarView?.editSubType ?? .template updateHeaderFooterDocument() } func updateHeaderFooterDocument() { guard let controller = headerFooterViewController else { return } controller.pdfDocument = nil let editDocument = CPDFDocument.init() let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) headerFooterViewController?.totalPDFCount = Int(listView.document.pageCount) headerFooterViewController?.pdfDocument = editDocument headerFooterViewController?.resetUI() headerFooterViewController?.reloadData() } func removeHeaderFooter() { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Are you sure you want to remove the Header & Footer?", comment: "") alert.addButton(withTitle: NSLocalizedString("Delete", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result == .alertFirstButtonReturn) { let headerFooter = listView.document.headerFooter() headerFooter?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Header & Footer removed"), type: .success, fromView: bottomContendBox, point:CGPointMake(CGRectGetWidth(bottomContendBox.frame)/2, CGRectGetHeight(bottomContendBox.frame)-28)) } } func batchAddHeaderFooter() { self.showBatchWindow(type: .headerAndFooter, files: nil) } func batchRemoveHeaderFooter() { self.showBatchWindow(type: .batchRemove, files: nil) } //MARK: - Bates func showBatesController() { viewManager.editType = .bates showEditToolbarView() editToolbarView?.editType = viewManager.editType if KMBatesManager.defaultManager.datas.count == 0 { editToolbarView?.editSubType = .add } else { editToolbarView?.editSubType = .template } editToolbarView?.reloadData() if batesViewController == nil { batesViewController = KMBatesController.init() } batesViewController?.view.frame = CGRectMake(44, 0, CGRectGetWidth(bottomContendBox.frame)-44, CGRectGetHeight(bottomContendBox.frame)) batesViewController?.view.autoresizingMask = [.maxXMargin, .width, .height] batesViewController?.delegate = self batesViewController?.totalPDFCount = Int(listView.document.pageCount) bottomContendBox.contentView?.addSubview(batesViewController!.view) batesViewController?.editSubType = editToolbarView?.editSubType ?? .template updateBatesDocument() batesViewController?.resetUI() } func updateBatesDocument() { guard let controller = batesViewController else { return } controller.pdfDocument = nil let editDocument = CPDFDocument.init() let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) batesViewController?.pdfDocument = editDocument batesViewController?.reloadData() } func removePDFBates() { let alert = NSAlert() alert.alertStyle = .warning alert.messageText = NSLocalizedString("Are you sure you want to remove the Bates?", comment: "") alert.addButton(withTitle: NSLocalizedString("Delete", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result == .alertFirstButtonReturn) { let bates = listView.document.bates() bates?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Bates removed"), type: .success, fromView: bottomContendBox, point:CGPointMake(CGRectGetWidth(bottomContendBox.frame)/2, CGRectGetHeight(bottomContendBox.frame)-28)) } } func batchAddBates() { self.showBatchWindow(type: .batesNumber, files: nil) } func batchRemoveBates() { self.showBatchWindow(type: .batchRemove, files: nil) } //MARK: - Crop Action // 白边距,统一大小 @objc func auto_cropPagesWhiteMargin(_ pageIndexs: [UInt]) { var size = NSZeroSize for i in pageIndexs { 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)) } var rectArray: Array = [] for i in pageIndexs { 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) } self.cropPages(atIndexs: pageIndexs, to: rectArray) } func cropPages(atIndexs pageIndexs: [UInt], 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 pageIndexs { if 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(atIndexs: pageIndexs, to: oldRectArray) /// 刷新预览视图 self.listView.layoutDocumentView() self.listView.displayBox = .cropBox self.listView.go(to: currentPage) self.listView.go(to: visibleRect, on: currentPage) } //MARK: - 文件对比 func beginCompareAction(_ index: Int) { 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 } NSWindow.currentWindow().beginSheet(controller.window!) } //文件对比 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.isCompareModel = false view.removeFromSuperview() } contendBox.addSubview(compareContentView) compareContentView.frame = contendBox.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!]) } } } contendBox.addSubview(coveringView) coveringView.frame = contendBox.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 } } //MARK: - TTS @IBAction func startSpeaking(_ sender: Any?) { self.showTTSWindow() let ttsView = KMTTSWindowController.share // ttsView.buttonItemClick_Play(ttsView.playButton) } @IBAction func stopSpeaking(_ sender: Any) { let ttsWindowC = KMTTSWindowController.share if ttsWindowC.pdfView?.document?.documentURL.path == self.listView.document?.documentURL.path { if let data = ttsWindowC.window?.isVisible, data { ttsWindowC.stopSpeaking() ttsWindowC.close() } } } 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) } ttsView.closeWindowCallback = { (isCloseWindow: Bool) in if isCloseWindow { } } 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() } } //MARK: 导出图片 func extractImageAction(num: Int) { if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.kEventName = "Reading_ExtractImage_BuyNow" winC?.showWindow(nil) 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 self.km_beginSheet(windowC: extract!) extract?.selectCurrentPageBtn() } func beginProgressSheet(withMessage message: String, maxValue: UInt) { 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] } //MARK: - 打印 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) } //Poster func showPosterPrintWindow() { guard let document = self.document else { return } guard let pdfDocument = PDFDocument(url: document.documentURL) else { return } if self.posterPrintWindowController == nil { posterPrintWindowController = KMPDFPosterPrintWindowController.init(pdfDocument: pdfDocument) } if let window = posterPrintWindowController?.window { NSApp.mainWindow?.beginSheet(window, completionHandler: { response in }) } } //Multiple func showMultiplePrintWindow() { guard let document = self.document else { return } guard let pdfDocument = PDFDocument(url: document.documentURL) else { return } if self.multiplePrintWindowController == nil { multiplePrintWindowController = KMPDFMultiplePrintWindowController.init(pdfDocument: pdfDocument) } if let window = multiplePrintWindowController?.window { NSApp.mainWindow?.beginSheet(window, completionHandler: { response in }) } } //Booklet func showBookletPrintWindow() { guard let document = self.document else { return } guard let pdfDocument = PDFDocument(url: document.documentURL) else { return } if self.bookletWindowController == nil { bookletWindowController = KMPDFBookletWindowController.init(document: pdfDocument) } if let window = bookletWindowController?.window { NSApp.mainWindow?.beginSheet(window, completionHandler: { response in }) } } //MARK: - FileInfo func showFileInfo() { KMInfoWindowController.shared.showWindow(nil) } //MARK: - Share Action @objc private func shareDocument(sender: NSView) { 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.window != nil { picker.show(relativeTo: sender.bounds, of: sender, 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: NSView) { 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.window != nil { picker.show(relativeTo: sender.bounds, of: sender, 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: NSView) { 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 } 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.window != nil { picker.show(relativeTo: sender.bounds, of: sender, 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 shareFromService(sender: NSMenuItem) { if ((NSApp.mainWindow?.windowController is KMBrowserWindowController) == false) { return } var string = "" if let freeTextAnnotation = listView.activeAnnotation as? CPDFFreeTextAnnotation { string = freeTextAnnotation.contents ?? "" } else if let markupAnnotation = listView.activeAnnotation as? CPDFMarkupAnnotation { if let page = markupAnnotation.page { if let selection = page.selection(for: markupAnnotation.bounds) { string = selection.string() ?? "" } } } else { string = listView.currentSelection?.string() ?? "" } let windowControler = NSApp.mainWindow?.windowController as! KMBrowserWindowController let model = windowControler.browser?.tabStripModel if let cnt = model?.count(), cnt <= 0 { return } if let data = model?.activeTabContents().isHome, data { return } let document: KMMainDocument = model?.activeTabContents() as! KMMainDocument if string.count > 0 { let represent : NSSharingService = sender.representedObject as! NSSharingService represent.perform(withItems: [string]) return } let represent = sender.representedObject as? NSSharingService represent?.perform(withItems: [string]) } //MARK: - PDFView Menu func clickPresentationMenu(point:NSPoint)->KMNMenuStruct { var viewHeight: CGFloat = 8 var menuItemArr: [ComponentMenuitemProperty] = [] var items: [(String, String)] = [] items.append(("Next Page", PDFViewMenuIdentifier_PageNext)) items.append(("Previous Page", PDFViewMenuIdentifier_PagePrevious)) items.append(("First", PDFViewMenuIdentifier_PageFirst)) items.append(("Last", PDFViewMenuIdentifier_PageLast)) items.append(("", "")) items.append(("Laser pointer", PDFViewMenuIdentifier_Presentation_LaserPoint)) items.append(("Brush", PDFViewMenuIdentifier_Presentation_Brush)) items.append(("", "")) items.append(("Exit Presentation", PDFViewMenuIdentifier_Presentation_Exit)) for (i, value) in items { if value.count == 0 { let property: ComponentMenuitemProperty = ComponentMenuitemProperty.divider() menuItemArr.append(property) viewHeight += 8 } else { let properties_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false, itemSelected: false, isDisabled: false, keyEquivalent: nil, text: KMLocalizedString(i), identifier: value,representedObject: point) if value == PDFViewMenuIdentifier_PageNext { properties_Menuitem.keyEquivalent = "▶" } else if value == PDFViewMenuIdentifier_PagePrevious { properties_Menuitem.keyEquivalent = "◀" } else if value == PDFViewMenuIdentifier_PageFirst { properties_Menuitem.keyEquivalent = "⌘ ◀" } else if value == PDFViewMenuIdentifier_PageLast { properties_Menuitem.keyEquivalent = "⌘ ▶" } else if value == PDFViewMenuIdentifier_Presentation_Exit { properties_Menuitem.keyEquivalent = "ESC" } if(value == PDFViewMenuIdentifier_Presentation_LaserPoint) { if((listView.presentationDrawView != nil) && listView.presentationDrawView.isHidden == false) { } else { properties_Menuitem.righticon = NSImage(named: "KMNImageNameMenuSelect") } } else if value == PDFViewMenuIdentifier_Presentation_Brush { if((listView.presentationDrawView != nil) && listView.presentationDrawView.isHidden == false) { properties_Menuitem.righticon = NSImage(named: "KMNImageNameMenuSelect") } else { } } menuItemArr.append(properties_Menuitem) viewHeight += 36 } } let menuStruct = KMNMenuStruct(menuitems: menuItemArr, viewHeight: viewHeight) return menuStruct } func gotoPage(_ sender: Any?) { var pages : [String] = [] for i in 0 ..< self.listView.document.pageCount { pages.append("\(i)") } self.textFieldSheet.callback = { [weak self] stringValue in guard let index = Int(stringValue) else { return } if (self?.listView == nil) { return } if (index > 0 && index <= self!.listView.document.pageCount) { self?.listView.go(toPageIndex: index-1, animated: true) } } self.textFieldSheet.showWindow(nil) self.textFieldSheet.pageBox.addItems(withObjectValues: pages) self.textFieldSheet.stringValue = "\(self.listView.currentPageIndex+1)" } //MARK: - 添加书签 @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.listView.undoManager?.setActionName("")//添加undo事件就可删除 } //MARK: - 页面旋转 func rotateLeft(page:CPDFPage,listView:CPDFListView?) { Task { @MainActor in let rotation = page.rotation page.leftRotate() listView?.layoutDocumentView() if(listView == self.listView) { var pageIndexes = IndexSet() pageIndexes.insert(Int(page.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) } } } func rotateRight(page:CPDFPage,listView:CPDFListView?) { Task { @MainActor in let rotation = page.rotation page.rightRotate() listView?.layoutDocumentView() if(listView == self.listView) { var pageIndexes = IndexSet() pageIndexes.insert(Int(page.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) } } } //MARK: - 自动滚动 func isAutoFlowOn() -> Bool { return listView.isAutoFlow() } func toggleAutoFlow(_ sender: Any?) { if (listView.isAutoFlow()) { listView.stopAutoFlow() } else { listView.startAutoFlow() } } //MARK: - 高亮Form func highlightFormFiled(_ sender: Any?) { let enabled = CPDFKitConfig.sharedInstance().enableFormFieldHighlight() CPDFKitConfig.sharedInstance().setEnableFormFieldHighlight(!enabled) listView.setNeedsDisplayForVisiblePages() } //MARK: - 高亮Link func highlightLinks(_ sender: Any?) { let enabled = CPDFKitConfig.sharedInstance().enableLinkFieldHighlight() CPDFAnnotation.updateLinkFieldHighlight(listView, linkFieldHighlight: !enabled) } //MARK: - 重置Form func resetForm(_ sender: Any?) { listView.resetFormAnnotation() } //MARK: - 属性 @IBAction func menuItemAction_property(_ sender: Any?) { KMInfoWindowController.shared.showWindow(sender) } //MARK: - 打印 @IBAction func menuItemAction_print(_ sender: Any?) { self.showPrintWindow() } //MARK: - Flattened func saveAsFlattenedPDFAction() { DispatchQueue.main.async { NSPanel.savePanel(self.view.window!, true) { panel in panel.nameFieldStringValue = self.listView.document.documentURL.deletingPathExtension().lastPathComponent + "_flatten" + ".pdf" } completion: { response, url, isOpen in if (response == .cancel) { return } var result = self.listView.document.writeFlatten(to: url!) if (!result) { return } if (isOpen) { NSDocumentController.shared.km_safe_openDocument(withContentsOf: url!, display: true) { _, _, _ in } } else { NSWorkspace.shared.activateFileViewerSelecting([url!]) } } } } func showInFinder() { NSWorkspace.shared.activateFileViewerSelecting([self.listView.document.documentURL]) } //MARK: - DisplayViewMode func getPDFViewPageLayoutType() -> pageLayoutType { if listView.displayMode() == .singlePage { return .singlePage } else if listView.displayMode() == .singlePageContinuous { return .singlePageContinue } else if listView.displayMode() == .twoUp { if listView.displaysAsBook == true { return .bookMode } return .twoPage } else if listView.displayMode() == .twoUpContinuous { if listView.displaysAsBook == true { return .bookMode } return .twoPageContinue } return .singlePage } func updatePDFViewDisplayMode(viewMode mode: CPDFDisplayViewMode = .singlePage, isbookMode bookMode: Bool = false, direction directionValue: CPDFDisplayDirection? = nil) { if bookMode == true { //书本模式 listView.displaysAsBook = true listView.displayTwoUp = true if let value = directionValue { listView.displayDirection = value } } else { listView.setDisplay(mode) } listView.layoutDocumentView() } //MARK: - 新增大纲 @objc func addOutLineItemAction() { botaViewController?.outlineViewC.addOutline() } //MARK: - 搜索 @objc func searchBaiduAction() { let label = self.listView.currentSelection?.string() ?? "" let query = label.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" if let url = URL(string: "https://www.baidu.com/s?wd=\(query)") { NSWorkspace.shared.open(url) } } //MARK: - 转档 func showConvertWindow(_ convertType: KMPDFConvertType) { if convertType == .word { let winC = KMConvertWordWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .ppt { let winC = KMConvertPPTsWindowController() winC.subType = 1 let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .rtf { let winC = KMConvertPPTsWindowController() winC.subType = 2 let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .text { let winC = KMConvertPPTsWindowController() winC.subType = 4 let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .csv { let winC = KMConvertPPTsWindowController() winC.subType = 5 let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .excel { let winC = KMConvertExcelWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .html { let winC = KMConvertHtmlWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if convertType == .json { let winC = KMConvertJsonWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: view.window, completionHandler: nil) } else if convertType == .jpeg || convertType == .jpg || convertType == .png || convertType == .gif || convertType == .tiff || convertType == .tga || convertType == .bmp || convertType == .jp2{ let winC = KMConvertImageWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: view.window, completionHandler: nil) if let settingView = winC.settingView as? KMConvertImageSettingView { settingView.selectConvertType(convertType: convertType) } } } //MARK: - 选择Form注释 @objc func selectAllFormAnnotation () { var formActiveAnnotations:[CPDFAnnotation] = [] for i in 0 ..< listView.document.pageCount { let page = listView.document.page(at: i) let annotations = page?.annotations for j in 0 ..< (annotations?.count ?? 0) { if let an = annotations?[j] as? CPDFAnnotation { if (an.isKind(of: CPDFWidgetAnnotation.self) == true) { formActiveAnnotations.append(an) } } } } listView.updateActiveAnnotations(formActiveAnnotations) } @objc func selectAllNomerAnnotation () { var normalActiveAnnotations:[CPDFAnnotation] = [] for i in 0 ..< listView.document.pageCount { let page = listView.document.page(at: i) let annotations = page?.annotations for j in 0 ..< (annotations?.count ?? 0) { if let an = annotations?[j] as? CPDFAnnotation { if an.isKind(of: CPDFWidgetAnnotation.self) == true || an.isKind(of: CPDFLinkAnnotation.self) == true || an.isKind(of: CPDFRedactAnnotation.self) == true { } else { normalActiveAnnotations.append(an) } } } } listView.updateActiveAnnotations(normalActiveAnnotations) } //MARK: 搜索 & 替换 func showSearchPopWindow(type: KMNBotaSearchType, keyborad: String?, replaceText: String?, results: [KMSearchMode]) { let toolMode = self.listView.toolMode let isEditing = self.listView.isEditing() var winH: CGFloat = 112 if type == .replace { if IAPProductsManager.default().isAvailableAllFunction() == false { let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.kEventName = "Reading_ReplaceText_BuyNow" winC?.showWindow(nil) return } if toolMode == .CEditPDFToolMode && isEditing { } else { // 进入内容编辑模式 viewManager.toolMode = .Edit updatePDFViewAnnotationMode() } winH = 208 } self.view.window?.makeFirstResponder(nil) let winC = KMSearchReplaceWindowController(with: listView, type: type) self.currentWindowController = winC winC.replaceCallback = { [weak self] in let toolMode = self?.listView.toolMode ?? .none let isEditing = self?.listView.isEditing() ?? false if toolMode == .CEditPDFToolMode && isEditing { } else { // 进入内容编辑模式 self?.viewManager.toolMode = .Edit self?.updatePDFViewAnnotationMode() } } winC.itemClick = { [weak self] idx, params in if idx == 1 { self?.toggleOpenLeftSide(pdfSideBarType: .search) guard let handdler = params.first as? KMNSearchHanddler else { return } let viewC = self?.botaViewController?.searchViewC viewC?.update(keyborad: handdler.searchKey, replaceKey: handdler.replaceKey, results: handdler.searchSectionResults) } } let targetView = self.pdfToolbarController?.leftViewButton let point = targetView?.convert(targetView?.frame.origin ?? .zero, to: nil) ?? .zero // 200 248 let x = point.x + (self.view.window?.frame.origin.x ?? 0) - 32 let y = point.y + (self.view.window?.frame.origin.y ?? 0) - winH - 32 let winFramePoint = NSPoint(x: x, y: y) winC.window?.setFrameOrigin(winFramePoint) winC.update(keyborad: keyborad, replaceKey: replaceText, results: results) self.view.window?.addChildWindow(winC.window!, ordered: .above) } // MARK: -显示加密弹窗 //MARK: - Redact密文 func showRedactProperty(readactAnnotation: CPDFRedactAnnotation?) { let properties = KMRedactPropertiesWindowController() properties.readactAnnotation = readactAnnotation self.km_beginSheet(windowC: properties) } //MARK: - 测量 func refreshMeasureInfo() { if distanceMeasureInfoWindowController == nil { distanceMeasureInfoWindowController = CDistanceMeasureInfoWindowController() } if perimeterMeasureInfoWindowController == nil { perimeterMeasureInfoWindowController = CPerimeterMeasureInfoWindowController() } if areaMeasureInfoWindowController == nil { areaMeasureInfoWindowController = CAreaMeasureInfoWindowController() } showMeasureFloatingWindowsIfNeed() } @objc func cancelMeasureType() { self.hideMeasureFloatingWindows() } func hideMeasureFloatingWindows() { if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.hideFloatingWindow() } else if perimeterMeasureInfoWindowController?.window?.isVisible == true { perimeterMeasureInfoWindowController?.hideFloatingWindow() } else if areaMeasureInfoWindowController?.window?.isVisible == true { areaMeasureInfoWindowController?.hideFloatingWindow() } } func showMeasureFloatingWindowsIfNeed() { cancelMeasureType() let toolMode = self.listView.toolMode if toolMode != .CNoteToolMode { return } if let data = self.listView.activeAnnotation as? CPDFPolylineAnnotation { } else if let data = self.listView.activeAnnotation as? CPDFPolygonAnnotation { } else if let data = self.listView.activeAnnotation as? CPDFLineAnnotation, data.isMeasure { } else { let type = self.listView.annotationType if type == .measureLine { distanceMeasureInfoWindowController?.measureInfo = listView.distanceMeasureInfo distanceMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .measurePolyLine { perimeterMeasureInfoWindowController?.measureInfo = listView.perimeterMeasureInfo perimeterMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .measurePolyGon { areaMeasureInfoWindowController?.measureInfo = listView.polygonAreaMeasureInfo areaMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .measureSquare { areaMeasureInfoWindowController?.measureInfo = listView.squareAreaMeasureInfo areaMeasureInfoWindowController?.window?.orderFront(nil) } else { cancelMeasureType() } } } func showMeasureSettingWindow() { let distanceSettingWC = CDistanceSettingWindowController(measureInfo: self.listView.distanceMeasureInfo) self.distanceMeasureInfoWindowController?.hideFloatingWindow() distanceSettingWC.delegate = self distanceSettingWC.own_beginSheetModal(for: self.view.window) { string in } } } //MARK: Compress extension KMMainViewController { func showCompressController(_ url: URL) { self.compressWindowController = KMCompressWindowController(windowNibName: "KMCompressWindowController") self.compressWindowController?.password = self.listView.document?.password ?? "" self.compressWindowController?.documentURL = url let controllerWindow = self.view.window controllerWindow?.beginSheet(self.compressWindowController!.window!) self.compressWindowController?.itemClick = { [unowned self] in controllerWindow?.endSheet((self.compressWindowController?.window)!) } self.compressWindowController?.batchAction = { [unowned self] view, filePaths in controllerWindow?.endSheet((self.compressWindowController?.window)!) self.showBatchWindow(type: .compress, files: filePaths) } self.compressWindowController?.resultCallback = { [unowned self] result, openDocument, fileURL, error in controllerWindow?.endSheet((self.compressWindowController?.window)!) if (result) { 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() } } } } //MARK: - OCR extension KMMainViewController { //window func showOCRWindow() { if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.showWindow(nil) return } let window = KMOCRSettingWindowController(windowNibName: "KMOCRSettingWindowController") window.OCRAction = {[unowned self] controller, model in self.convertOCRScanFile(window: window, document: self.listView.document, model: model) } self.km_beginSheet(windowC: window) } func showOCREditAlert() { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { [unowned self] in alertTipViewController.showInView(listView) alertTipViewController.reloadOCRAlertUI() alertTipViewController.reloadAlertUIFrame() alertTipViewController.OCRApplyCallback = { [unowned self] in self.showOCRWindow() } } } func closeOCREditAlert() { guard let view = alertTipViewController.OCRComponentAlert else { return } alertTipViewController.reloadOCRAlertUI() alertTipViewController.reloadAlertUIFrame() } func showOCRToolAlert(_ string: String) { let alertView = ComponentMessage() alertView.properties = ComponentMessageProperty(messageType: .normal_custom, title: KMLocalizedString(string)) alertView.frame = CGRectMake((CGRectGetWidth(self.listView.frame) - alertView.properties.propertyInfo.viewWidth) / 2, CGRectGetHeight(self.listView.frame) - alertView.properties.propertyInfo.viewHeight - 8, alertView.properties.propertyInfo.viewWidth, alertView.properties.propertyInfo.viewHeight) alertView.reloadData() self.listView.addSubview(alertView) // 自动移除视图 DispatchQueue.main.asyncAfter(deadline: .now() + 3) { self.removeOCRToolAlert(alertView) } } private func removeOCRToolAlert(_ alertView: NSView) { // 淡出动画 NSAnimationContext.runAnimationGroup({ context in context.duration = 0.3 alertView.animator().alphaValue = 0 }, completionHandler: { alertView.removeFromSuperview() }) } //OCR func convertOCRScanFile(window: KMOCRSettingWindowController, document: CPDFDocument, model: KMOCRModel) { window.beginLoading() //当前页面需要提前设置 if model.pageRangeType == .current { model.pageRange = [self.listView.currentPageIndex] } KMOCRManager.manager.convertScanFile(document: document, model: model, progress: { progress in }) { [weak self] document, text, error in window.endLoading() window.km_quick_endSheet() if !model.saveAsPDF { self?.listView.layoutDocumentView() } } } func convertOCR(document: CPDFDocument, model: KMOCRModel) { // self.view.window?.windowController.beginLoading() //当前页面需要提前设置 if model.pageRangeType == .current { model.pageRange = [self.listView.currentPageIndex] } self.showProgressWindow(message: "正在转换中....") KMOCRManager.manager.convertOCR(document: document, model: model, progress: { [weak self] progress in self?.progressC?.message = "正在转换中...." self?.progressC?.doubleValue = Double(progress * 100) }) { [weak self] document, text, error in // self?.view.window?.windowController.endLoading() // window.km_quick_endSheet() if !model.saveAsPDF { self?.listView.layoutDocumentView() } self?.hiddenProgressWindow() } self.progressC?.closeBlock = { print("手动取消中") KMOCRManager.manager.cancelRecognition() } } func convertOCRSaveAsTXT(text: String) { NSPanel.savePanel(NSWindow.currentWindow()) { panel in let url: URL = self.listView.document.documentURL panel.nameFieldStringValue = ""+url.deletingPathExtension().lastPathComponent+"_OCR" panel.allowedFileTypes = ["txt"] } completion: { [unowned self] response, url in if (response == .cancel) { return } let saveAsPDFFilePath = url?.path ?? "" let outputURL = URL(fileURLWithPath: saveAsPDFFilePath) try? text.write(to: outputURL, atomically: true, encoding: .utf8) } } func convertSelectionRectOCR(rect: NSRect) { let rect = NSIntegralRect(rect) let orgPage : CPDFPage = listView.currentSelectionPage() ?? CPDFPage() if let page : CPDFPage = orgPage.copy() as? CPDFPage { page.setBounds(rect, for: .cropBox) let image = page.thumbnail(of: rect.size) ?? NSImage() guard let model = self.rightSideController?.tool_OCRController?.model else { return } model.pageRange = [Int(orgPage.pageIndex())] KMOCRManager.manager.convertOCR(images: [image], model: model, progress: { progress in }) { [weak self] document, text, error in self?.rightSideController?.tool_OCRController?.model.text = text ?? "" self?.rightSideController?.tool_OCRController?.reloadData() //关闭窗口 self?.listView.selectionRect = NSZeroRect self?.listView.selectionPageIndex = UInt(NSNotFound) self?.closePopOperationWindow() self?.listView.setNeedsDisplayForVisiblePages() } } } } //Batch extension KMMainViewController { func showBatchWindow(type: KMBatchCollectionViewType, files: [URL]?) { let batchWindowController = KMBatchWindowController.init(windowNibName: "KMBatchWindowController") batchWindowController.window?.makeKeyAndOrderFront("") // var datas: [KMBatchProcessingTableViewModel] = [] // for file in files! { // let data = KMBatchProcessingTableViewModel.initWithFilePath(url: file) // datas.append(data) // } batchWindowController.inputData = files ?? [] batchWindowController.type = type // 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("") } } //MARK: - 代理方法 //MARK: - NSSplitViewDelegate extension KMMainViewController: NSSplitViewDelegate { func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool { if splitView == infoContendSplitView { return subview.isEqual(to: infoSplitCenterView) == false } return false } func splitView(_ splitView: NSSplitView, shouldCollapseSubview subview: NSView, forDoubleClickOnDividerAt dividerIndex: Int) -> Bool { if splitView == infoContendSplitView { if(subview.isEqual(to: infoSplitLeftView)) { } else if(subview.isEqual(to: infoSplitRightView)) { } } return false } func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool { if splitView == infoContendSplitView { return splitView == infoContendSplitView } else if splitView == pdfSplitView { return splitView == pdfSplitView } return false } func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { if splitView == infoContendSplitView { if dividerIndex == 0 { if viewManager.showDisplayView { return MIN_SIDE_PANE_WIDTH.doubleValue } return infoContendSplitView.bounds.width/2 } else if (dividerIndex == 1) { return proposedMaximumPosition - MIN_SIDE_PANE_WIDTH.doubleValue } } return proposedMaximumPosition } func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { if(splitView == infoContendSplitView && dividerIndex == 0) { return proposedMinimumPosition + MIN_SIDE_PANE_WIDTH.doubleValue } return proposedMinimumPosition } func splitViewDidResizeSubviews(_ notification: Notification) { let splitView = notification.object as? NSSplitView if(splitView == infoContendSplitView) { leftSplitViewResizeFinish() if(newMwcFlags.settingUpWindow == false && self.view.window?.frameAutosaveName != nil) { let leftWidth = infoContendSplitView.isSubviewCollapsed(infoSplitLeftView) ? 0.0 : infoSplitLeftView.frame.width UserDefaults.standard.set(leftWidth, forKey: CPDFViewLeftSidePaneWidthKey) UserDefaults.standard.synchronize() } if listView.isEditing() == false { updateAnnotationsPopWinodwFrame() } else { updateContentEditPopWinodwFrame() } } NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(splitViewResizeFinish), object: nil) self.perform(#selector(splitViewResizeFinish), with: nil, afterDelay: 0.15) } @objc func leftSplitViewResizeFinish() { botaViewController?.changeLeftSideBounds() } @objc func splitViewResizeFinish() { if infoContendSplitView.isSubviewCollapsed(infoSplitLeftView) { if viewManager.pdfSideBarType != .none { viewManager.pdfSideBarType = .none sideBarController?.reloadBOTAData() } } } } //MARK: - KMPDFSideBarControllerDelegate 左侧Sidebar代理 extension KMMainViewController: KMPDFSideBarControllerDelegate { func kmPDFSideBarControllerDidSidebarTypeUpdated(_ view: KMPDFSideBarController) { if viewManager.pdfSideBarType == .none { toggleCloseLeftSide() } else { toggleOpenLeftSide(pdfSideBarType: viewManager.pdfSideBarType) } } func kmPDFSideBarControllerDidGotoPage(_ view: KMPDFSideBarController, _ pageIndex: Int) { listView.go(toPageIndex: pageIndex, animated: true) } } //MARK: - KMPDFToolbarControllerDelegate 工具栏代理 extension KMMainViewController: KMPDFToolbarControllerDelegate { //MARK: -ViewTools发生变化时调用 func kmPDFToolbarControllerDidViewToolsChanged(_ controller: KMPDFToolbarController) { let viewToolsType = viewManager.viewToolsType if viewToolsType == .Select { listView.toolMode = .CNoteToolMode } else if viewToolsType == .Scroll { listView.toolMode = .CMoveToolMode } else if viewToolsType == .Content_Selection { listView.toolMode = .CSelectToolMode } else if viewToolsType == .Magnify { listView.toolMode = .CMagnifyToolMode } else if viewToolsType == .AreaZoom { listView.toolMode = .CSelectZoomToolMode } refreshToolbarViewHeightInfo() } //MARK: -一级工具栏状态发生变化时调用 func kmPDFToolbarControllerDidToolModeChanged(_ controller: KMPDFToolbarController) { refreshToolbarViewHeightInfo() toolbarViewModeChanged() } //MARK: -点击工具栏按钮 func kmPDFToolbarControllerDidToolbarItemClicked(_ controller: KMPDFToolbarController, _ itemIdentifier: String) { print("toolbar点击", itemIdentifier) if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_PageEdit_Identifier).contains(itemIdentifier) { //MARK: -页面编辑 if itemIdentifier == KMPDFToolbar_PageEdit_InsertFile_Identifier { pageEditViewController?.insertFromPDFAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_InsertBlank_Identifier { pageEditViewController?.insertFromBlankAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_InsertClip_Identifier { pageEditViewController?.insertFromClipboardAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_InsertScanner_Identifier { pageEditViewController?.insertFromScannerAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Extract_Identifier { pageEditViewController?.extractPDFAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Replace_Identifier { pageEditViewController?.replacePDFAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Split_Identifier { pageEditViewController?.splitPDFAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Reverse_Identifier { pageEditViewController?.reversePDFAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_LeftRotate_Identifier { pageEditViewController?.rotatePageLeftAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_RightRotate_Identifier{ pageEditViewController?.rotatePageRightAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Delete_Identifier { pageEditViewController?.deletePageAction() } else if itemIdentifier == KMPDFToolbar_PageEdit_Reduce_Identifier { pageEditViewController?.zoomOutPageAction() if(pageEditViewController?.canZoomInPageSize() == false) { toolbarManager.page_Increase_Property.isDisabled = true } else { toolbarManager.page_Increase_Property.isDisabled = false } if(pageEditViewController?.canZoomOutPageSize() == false) { toolbarManager.page_Reduce_Property.isDisabled = true } else { toolbarManager.page_Reduce_Property.isDisabled = false } controller.refreshSecondToolbarItemsState() } else if itemIdentifier == KMPDFToolbar_PageEdit_Increase_Identifier { pageEditViewController?.zoomInPageAction() if(pageEditViewController?.canZoomInPageSize() == false) { toolbarManager.page_Increase_Property.isDisabled = true } else { toolbarManager.page_Increase_Property.isDisabled = false } if(pageEditViewController?.canZoomOutPageSize() == false) { toolbarManager.page_Reduce_Property.isDisabled = true } else { toolbarManager.page_Reduce_Property.isDisabled = false } controller.refreshSecondToolbarItemsState() } else if itemIdentifier == KMPDFToolbar_PageEdit_page_oddPage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .odd if(toolbarManager.page_pageInfo_Property.creatable == true) { toolbarManager.page_pageInfo_Property.creatable = false controller.refreshSecondToolbarItemsState() } } else if itemIdentifier == KMPDFToolbar_PageEdit_page_EvenPage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .even if(toolbarManager.page_pageInfo_Property.creatable == true) { toolbarManager.page_pageInfo_Property.creatable = false controller.refreshSecondToolbarItemsState() } } else if itemIdentifier == KMPDFToolbar_PageEdit_page_PortraitPage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .horizontal if(toolbarManager.page_pageInfo_Property.creatable == true) { toolbarManager.page_pageInfo_Property.creatable = false controller.refreshSecondToolbarItemsState() } } else if itemIdentifier == KMPDFToolbar_PageEdit_page_LandscapePage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .vertical if(toolbarManager.page_pageInfo_Property.creatable == true) { toolbarManager.page_pageInfo_Property.creatable = false controller.refreshSecondToolbarItemsState() } } else if itemIdentifier == KMPDFToolbar_PageEdit_page_AllPage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .allPage if(toolbarManager.page_pageInfo_Property.creatable == true) { toolbarManager.page_pageInfo_Property.creatable = false controller.refreshSecondToolbarItemsState() } } else if itemIdentifier == KMPDFToolbar_PageEdit_page_CustomPage_Identifier { pageEditViewController?.thumbnailChoosePageStyle = .custom toolbarManager.page_pageInfo_Property.text = nil if(toolbarManager.page_pageInfo_Property.creatable == false) { toolbarManager.page_pageInfo_Property.creatable = true } controller.refreshSecondToolbarItemsState() } } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Markup_Identifier).contains(itemIdentifier) { //MARK: -Markup if itemIdentifier == KMPDFToolbar_eye_Identifier { self.showOrHideNotes() } if viewManager.subToolMode == .None { viewManager.showRightSide = false } else { viewManager.showRightSide = true } self.refreshToolbarRightViewInfo() toolbarViewModeChanged() } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Edit_Identifier).contains(itemIdentifier) { //MARK: -编辑 if itemIdentifier == KMPDFToolbar_edit_addWatermark_Identifier { showWatermarkController() } else if itemIdentifier == KMPDFToolbar_edit_removeWatermark_Identifier { removePDFWatermark() } else if itemIdentifier == KMPDFToolbar_edit_batch_AddWatermark_Identifier { batchAddWatermark() } else if itemIdentifier == KMPDFToolbar_edit_batchRemoveWatermark_Identifier { batchRemoveWatermark() } else if itemIdentifier == KMPDFToolbar_edit_addBG_Identifier { showBackgroundController() } else if itemIdentifier == KMPDFToolbar_edit_removeBG_Identifier { removePDFBackground() } else if itemIdentifier == KMPDFToolbar_edit_batch_AddBG_Identifier { batchAddBackground() } else if itemIdentifier == KMPDFToolbar_edit_batchRemoveBG_Identifier { batchRemoveBackground() } else if itemIdentifier == KMPDFToolbar_edit_addHF_Identifier { showHeaderFooterController() } else if itemIdentifier == KMPDFToolbar_edit_removeHF_Identifier { removeHeaderFooter() } else if itemIdentifier == KMPDFToolbar_edit_batch_AddHF_Identifier { batchAddHeaderFooter() } else if itemIdentifier == KMPDFToolbar_edit_batchRemoveHF_Identifier { batchRemoveHeaderFooter() } else if itemIdentifier == KMPDFToolbar_edit_addBates_Identifier { showBatesController() } else if itemIdentifier == KMPDFToolbar_edit_removeBates_Identifier { removePDFBates() } else if itemIdentifier == KMPDFToolbar_edit_batch_AddBates_Identifier { batchAddBates() } else if itemIdentifier == KMPDFToolbar_edit_batchRemoveBates_Identifier { batchRemoveBates() } else if itemIdentifier == KMPDFToolbar_edit_crop_Identifier { showCropController() } if viewManager.subToolMode == .None { viewManager.showRightSide = false } else { viewManager.showRightSide = true } self.refreshToolbarRightViewInfo() toolbarViewModeChanged() } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Form_Identifier).contains(itemIdentifier) { //MARK: -Form表单 if itemIdentifier == KMPDFToolbar_form_HighlightFields_Identifier { let value = CPDFKitConfig.sharedInstance().enableFormFieldHighlight() CPDFAnnotation.updateHighlightFormFiled(listView, highlightFormFiled: !value) self.toolbarManager.refreshDefaultConfigItem() } else if itemIdentifier == KMPDFToolbar_form_ShowName_Identifier { listView.showFormFieldName = !listView.showFormFieldName if listView.showFormFieldName { toolbarManager.form_ShowName_Property.righticon = NSImage(named: "tick_Green") } else { toolbarManager.form_ShowName_Property.righticon = nil } listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_ClearForm_Identifier { listView.resetFormAnnotation() } else if itemIdentifier == KMPDFToolbar_form_Align_Left_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .left) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Align_Hori_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .horizontally) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Align_Right_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .right) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Align_Top_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .top) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Align_Vert_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .vertical) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Align_Bottom_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .bottom) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Distribute_Vert_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .disVertical) listView.setNeedsDisplayForVisiblePages() } else if itemIdentifier == KMPDFToolbar_form_Distribute_Hori_Identifier { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .disHorizontally) listView.setNeedsDisplayForVisiblePages() } if viewManager.subToolMode == .None { viewManager.showRightSide = false } else { viewManager.showRightSide = true } self.refreshToolbarRightViewInfo() if itemIdentifier == KMPDFToolbar_form_HighlightFields_Identifier || itemIdentifier == KMPDFToolbar_form_ShowName_Identifier || itemIdentifier == KMPDFToolbar_form_ClearForm_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Left_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Hori_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Right_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Top_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Vert_Identifier || itemIdentifier == KMPDFToolbar_form_Align_Bottom_Identifier || itemIdentifier == KMPDFToolbar_form_Distribute_Vert_Identifier || itemIdentifier == KMPDFToolbar_form_Distribute_Hori_Identifier { } else { toolbarViewModeChanged() } } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Fill_Identifier).contains(itemIdentifier) { //MARK: -填充 if viewManager.subToolMode == .None { viewManager.showRightSide = false } else { viewManager.showRightSide = true } self.refreshToolbarRightViewInfo() toolbarViewModeChanged() } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Convert_Identifier).contains(itemIdentifier) { //MARK: -转档 if itemIdentifier == KMPDFToolbar_convert_word_Identifier { self.showConvertWindow(.word) } else if itemIdentifier == KMPDFToolbar_convert_ppt_Identifier { self.showConvertWindow(.ppt) } else if itemIdentifier == KMPDFToolbar_convert_RTF_Identifier { self.showConvertWindow(.rtf) } else if itemIdentifier == KMPDFToolbar_convert_Text_Identifier { self.showConvertWindow(.text) } else if itemIdentifier == KMPDFToolbar_convert_CSV_Identifier { self.showConvertWindow(.csv) } else if itemIdentifier == KMPDFToolbar_convert_excel_Identifier { self.showConvertWindow(.excel) } else if itemIdentifier == KMPDFToolbar_convert_HTML_Identifier { self.showConvertWindow(.html) } else if itemIdentifier == KMPDFToolbar_convert_Json_Identifier { self.showConvertWindow(.json) } else if itemIdentifier == KMPDFToolbar_convert_image_Identifier { self.showConvertWindow(.jpeg) } else if itemIdentifier == KMPDFToolbar_convert_imageToPDF_Identifier { NSApplication.ShowImageToPDFWindow() } self.refreshToolbarRightViewInfo() toolbarViewModeChanged() } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Protect_Identifier).contains(itemIdentifier) { //MARK: -Protect if itemIdentifier == KMPDFToolbar_protect_redact_Identifier { toolbarViewModeChanged() } else if itemIdentifier == KMPDFToolbar_protect_redact_Property_Identifier { self.showRedactProperty(readactAnnotation: nil) toolbarViewModeChanged() } else if itemIdentifier == KMPDFToolbar_protect_redact_Apply_Identifier { toolbarViewModeChanged() } else if itemIdentifier == KMPDFToolbar_protect_redact_Exit_Identifier { toolbarViewModeChanged() } else if itemIdentifier == KMPDFToolbar_protect_security_Identifier { self.showSecureWindow() } else if itemIdentifier == KMPDFToolbar_protect_removeSecurity_Identifier { self.showRemoveSecureWindow() } else if itemIdentifier == KMPDFToolbar_protect_digitalSign_Identifier { } } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Tools_Identifier).contains(itemIdentifier) { //MARK: -工具 if itemIdentifier == KMPDFToolbar_tools_compress_Identifier { self.showCompressController(self.listView.document.documentURL) } else if itemIdentifier == KMPDFToolbar_tools_batch_compress_Identifier { self.showBatchWindow(type: .compress, files: [self.listView.document.documentURL]) } else if itemIdentifier == KMPDFToolbar_tools_OCR_Identifier { viewManager.showRightSide = !viewManager.showRightSide self.refreshToolbarRightViewInfo() } else if itemIdentifier == KMPDFToolbar_tools_merge_Identifier { self.showMergeWindow(self.listView.document.password) } else if itemIdentifier == KMPDFToolbar_tools_TTS_Identifier { self.showTTSWindow() } else if itemIdentifier == KMPDFToolbar_tools_extractImage_Identifier { self.extractImageAction(num: 2) } else if itemIdentifier == KMPDFToolbar_tools_AITools_Identifier { self.viewManager.pdfSideBarType = .aiTools self.sideBarController?.reloadData() if let sideVC = self.sideBarController { self.kmPDFSideBarControllerDidSidebarTypeUpdated(sideVC) } } else if itemIdentifier == KMPDFToolbar_tools_compare_side_Identifier { self.beginCompareAction(1) } else if itemIdentifier == KMPDFToolbar_tools_compare_Overlay_Identifier { self.beginCompareAction(2) } else if itemIdentifier == KMPDFToolbar_tools_batch_Identifier { self.showBatchWindow(type: .convertPDF, files: [self.listView.document.documentURL]) } if viewManager.subToolMode == .None { viewManager.showRightSide = false } else { viewManager.showRightSide = true } self.refreshToolbarRightViewInfo() toolbarViewModeChanged() } else if itemIdentifier == KMPDFToolbar_ViewDisplay_Identifier { //MARK: -Display updatePDFDisplaySettingView() } else if toolbarManager.getSubToolItemIdentifys(KMPDFToolbar_Right_Identifiers).contains(itemIdentifier) { if(itemIdentifier == KMPDFToolbar_undo_Identifier) { //MARK: -Undo listView.undoManager?.undo() } else if(itemIdentifier == KMPDFToolbar_redo_Identifier) { //MARK: -Redo listView.undoManager?.redo() } else if(itemIdentifier == KMPDFToolbar_fileInfo_Identifier) { self.showFileInfo() } else if(itemIdentifier == KMPDFToolbar_share_PDF_Identifier || itemIdentifier == KMPDFToolbar_share_Flattened_Identifier || itemIdentifier == KMPDFToolbar_share_Original_Identifier) { //MARK: -Share if(itemIdentifier == KMPDFToolbar_share_PDF_Identifier) { if let view = controller.findViewWith(KMPDFToolbar_share_Identifier) { shareDocument(sender: view) } } else if(itemIdentifier == KMPDFToolbar_share_Flattened_Identifier) { if let view = controller.findViewWith(KMPDFToolbar_share_Identifier) { shareFlatten(sender: view) } } else if(itemIdentifier == KMPDFToolbar_share_Original_Identifier) { if let view = controller.findViewWith(KMPDFToolbar_share_Identifier) { shareOriginalPDF(sender: view) } } } else if itemIdentifier == KMPDFToolbar_save_Identifier { myDocument?.save(nil) } else if itemIdentifier == KMPDFToolbar_print_Identifier { self.showPrintWindow() } else if itemIdentifier == KMPDFToolbar_tts_Identifier { self.showTTSWindow() } else if itemIdentifier == KMPDFToolbar_ppt_Identifier { self.togglePresentation(nil) } } else if itemIdentifier == KMPDFToolbar_PageEdit_Identifier { //MARK: -页面编辑 if viewManager.isPageEditMode == true { enterPageEditMode() } else { exitPageEditMode() } } else if itemIdentifier == KMPDFToolbar_rightView_Identifier { //MARK: -属性栏 self.refreshToolbarRightViewInfo() } else { print("click else") } refreshToolbarViewHeightInfo() refreshRightSide() } func kmPDFToolbarControllerDidSelectTextDidBeginEditing(_ controller: KMPDFToolbarController, _ view: ComponentSelect) { } func kmPDFToolbarControllerDidSelectTextDidChange(_ controller: KMPDFToolbarController, _ view: ComponentSelect) { } func kmPDFToolbarControllerDidSelectTextDidEndEditing(_ controller: KMPDFToolbarController, _ view: ComponentSelect) { if view.properties == toolbarManager.page_pageInfo_Property { if viewManager.isPageEditMode == true { let fileAttribute = KMNFileAttribute() fileAttribute.password = listView.document?.password ?? "" fileAttribute.pdfDocument = listView.document fileAttribute.filePath = listView.document?.documentURL.path ?? "" fileAttribute.bAllPage = false fileAttribute.pagesType = .PagesString fileAttribute.pagesString = view.properties.text ?? "" let fetchSelectPages = fileAttribute.fetchSelectPages() if (fetchSelectPages.isEmpty) { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = String(format: "%@ %@", fileAttribute.filePath.lastPathComponent, KMLocalizedString("Invalid page range or the page number is out of range. Please try again.")) alert.runModal() toolbarManager.page_pageInfo_Property.text = "" controller.refreshSecondToolbarItemsState() } else { var tIndexPaths: Set = [] for i in 0 ..< fetchSelectPages.count { tIndexPaths.insert(IndexPath(item: (fetchSelectPages[i] - 1), section: 0)) } pageEditViewController?.selectionIndexPaths = tIndexPaths } } } } func kmPDFToolbarControllerDidExitPageEditMode(_ controller: KMPDFToolbarController) { exitPageEditMode() } } //MARK: - KMRightSideControllerDelegate右边属性栏代理 extension KMMainViewController: KMRightSideControllerDelegate { func kmRightSideControllerRotateLeft(_ annotations: [CPDFStampAnnotation], withPDFView pdfView: CPDFListView?) { CPDFStampAnnotation.rotateLeft(annotations, withPDFView: pdfView) (undoManager?.prepare(withInvocationTarget: self) as AnyObject).kmRightSideControllerRotateRight(annotations, withPDFView: pdfView) } func kmRightSideControllerRotateRight(_ annotations: [CPDFStampAnnotation], withPDFView pdfView: CPDFListView?) { CPDFStampAnnotation.rotateRight(annotations, withPDFView: pdfView) (undoManager?.prepare(withInvocationTarget: self) as AnyObject).kmRightSideControllerRotateLeft(annotations, withPDFView: pdfView) } func kmRightSideControllerDidContendVCUpdated(_ controller: KMRightSideController) { //MARK: -Crop if (controller.contentViewController is KMCropPropertyController) { if let cropVC = rightSideController?.edit_cropController { cropVC.pdfView = controller.pdfView if cropVC.delegate == nil { cropVC.delegate = cropController } cropVC.reloadData() } } reloadPopUIWindow() } func kmRightSideControllerOCRShowTypeChange(_ controller: KMRightSideController, _ type: KMOCRShowType) { if type == .area { self.listView.toolMode = .COCRToolMode self.showOCRToolAlert(KMLocalizedString("Please select the area that needs OCR and click the “OCR” button to start")) } else { self.listView.toolMode = .CTextToolMode } } func kmRightSideControllerOCRDoneAction(_ controller: KMRightSideController, _ model: KMOCRModel) { if model.showType == .area { self.convertOCRSaveAsTXT(text: model.text) } else { if model.saveAsPDF { if model.saveType == .PDF { } else { } } else { } self.convertOCR(document: self.listView.document, model: model) } } //测量设置界面 func kmRightSideControllerShowMeasureSetting(_ controller: KMRightSideController) { showMeasureSettingWindow() } } //MARK: - KMNDisplayViewControllerDelegate代理 extension KMMainViewController: KMNDisplayViewControllerDelegate { //Display Mode func displayViewControllerDidDisplayModeChanged(_ controller: KMNDisplayViewController) { listView.layoutDocumentView() } //阅读模式 func displayViewControllerDidReadModeUpdated(_ controller: KMNDisplayViewController) { if viewManager.isPDFReadMode { openPDFReadMode() } else { exitPDFReadMode() } } //PPT func displayViewControllerDidGotoSlideShow(_ controller: KMNDisplayViewController) { togglePresentation(nil) } //SplitView func displayViewControllerDidSplitModeChanged(_ controller: KMNDisplayViewController) { reloadPDFSplitInfo() } func displayViewControllerDidSplitFileChanged(_ controller: KMNDisplayViewController) { splitPDFController?.reloadData() } func displayViewControllerDidToolbarStateChanged(_ controller: KMNDisplayViewController) { splitPDFController?.refreshToolbarState() reloadPDFPageNumberToolbar() } } //MARK: - PPT extension KMMainViewController: KMInteractionProviderProtocol { func providerContentView(fullScreenWindow: NSWindow, inset: CGFloat) -> NSView? { if(interactionMode == .presentation) { if listView.presentationDrawView == nil { listView.createPresentationDraw() } presentationTopViewController = KMPresentationTopViewController.init(nibName: "KMPresentationTopViewController", bundle: nil) presentationTopViewController?.pdfView = listView 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 { listView.frame = NSInsetRect(fullScreenWindow.contentView?.bounds ?? .zero, 0, 0) } fullScreenWindow.contentView?.addSubview(listView) if(interactionMode == .presentation) { let frame = fullScreenWindow.frame listView.frame = CGRectMake(0, 0, frame.size.width, frame.size.height-42) listView.autoresizingMask = [.width, .maxYMargin] } return view } @objc func willEnterInteractionModeNotification(_ sender: Notification) { guard let win = sender.object as? NSWindow, win.isEqual(to: self.view.window) else { return } let interactionMode = sender.userInfo?[NSWindow.UserInfo.interactionModeKey] as? KMInteractionMode if interactionMode == .presentation { let backgroundColor = NSColor.black let level = UserDefaults.standard.bool(forKey: "SKUseNormalLevelForPresentationKey") ? NSWindow.Level.normal : NSWindow.Level.popUpMenu let wasInteractionMode = self.interactionMode if wasInteractionMode == .normal { self.savedNormalSetup.setDictionary(self.currentPDFSettings() as! [AnyHashable : Any]) } if wasInteractionMode == .legacyFullScreen { self.enterPresentationMode() self.listView.frame = (self.view.window?.contentView?.bounds)! self.view.window?.contentView?.addSubview(listView) // self.view.window?.backgroundColor = backgroundColor self.view.window?.level = level self.listView.layoutDocumentView() self.listView.requiresDisplay() } } else { KMPrint("2") } } @objc func didEnterInteractionModeNotification(_ sender: Notification) { guard let win = sender.object as? NSWindow, win.isEqual(to: self.view.window) else { return } if self.interactionMode == .presentation { self.listView.layoutDocumentView() self.listView.requiresDisplay() } } @objc func willShowFullScreenNotification(_ sender: Notification) { guard let win = sender.object as? NSWindow, win.isEqual(to: self.view.window) else { return } if self.interactionMode == .presentation { let view = self.view.window?.firstResponder as? NSView if let data = view?.isDescendant(of: self.pdfSplitView), data { self.view.window?.makeFirstResponder(nil) } } } @objc func didShowFullScreenNotification(_ sender: Notification) { guard let win = sender.object as? NSWindow, win.isEqual(to: self.view.window) else { return } if self.interactionMode == .presentation { self.enterPresentationMode() } } } // MARK: -KMPresentationTopViewControllerDelegate (幻灯片) extension KMMainViewController: KMPresentationTopViewControllerDelegate { func presentationTopViewExit(_ presentationTopViewController: KMPresentationTopViewController, withButton: NSButton) { self.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) } } } //MARK: - KMSplitPDFViewControllerDelegate SplitPDFView分屏视图 extension KMMainViewController: KMSplitPDFViewControllerDelegate { func splitPDFViewControllerDidUpdateFilePath(_ controller: KMSplitPDFViewController) { displaySettingController?.reloadData() } func splitPDFViewControllerDidUpdatePDFScale(_ controller: KMSplitPDFViewController) { if let scaleFactor = controller.pdfView?.scaleFactor { listView.scaleFactor = scaleFactor } } func splitPDFViewControllerDidUpdatePDFPageIndex(_ controller: KMSplitPDFViewController) { if let pageIndex = controller.pdfView?.currentPageIndex { listView.go(toPageIndex: pageIndex, animated: false) } } } //MARK: - Edit编辑相关代理 extension KMMainViewController: KMEditToolbarViewDelegate { func kmEditToolbarViewDidUpdateMode(_ view: KMEditToolbarView) { if view.editType == .watermark { watermarkViewController?.editSubType = editToolbarView?.editSubType ?? .template watermarkViewController?.resetUI() if editToolbarView?.editSubType == .template { watermarkViewController?.clearData() } watermarkViewController?.reloadData() } else if view.editType == .background { backgroundViewController?.editSubType = editToolbarView?.editSubType ?? .template backgroundViewController?.resetUI() backgroundViewController?.reloadData() } else if view.editType == .header_Footer { headerFooterViewController?.editSubType = editToolbarView?.editSubType ?? .template headerFooterViewController?.resetUI() headerFooterViewController?.reloadData() } else if view.editType == .bates { batesViewController?.editSubType = editToolbarView?.editSubType ?? .template batesViewController?.resetUI() batesViewController?.reloadData() } } func kmEditToolbarViewDidChooseBatch(_ view: KMEditToolbarView) { if view.editType == .watermark { self.showBatchWindow(type: .watermark, files: nil) } else if view.editType == .background { self.showBatchWindow(type: .background, files: nil) } else if view.editType == .header_Footer { self.showBatchWindow(type: .headerAndFooter, files: nil) } else if view.editType == .bates { self.showBatchWindow(type: .batesNumber, files: nil) } } func kmEditToolbarViewDidChooseApply(_ view: KMEditToolbarView) { let pageInfo = view.pageRangeSelectView.getSelectedPageIndex(listView.document) let pageIndex = pageInfo.0 let isCurrentPage = pageInfo.1 if pageIndex.isEmpty { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = KMLocalizedString("Invalid page range or the page number is out of range. Please try again.") alert.runModal() return } var pageString = view.pageRangeSelectView.getSelectedPageString(listView.document, pageIndex) if isCurrentPage { pageString = String(format: "%ld", listView.currentPageIndex) } if view.editType == .watermark { if let model = watermarkViewController?.currentWatermarkData { let watermark = KMPDFWatermarkData.returnWaterMarkWith(model, listView.document) watermark.pageString = pageString listView.document.addWatermark(watermark) listView.layoutDocumentView() } exitEditToolbarView() } else if view.editType == .background { if let model = backgroundViewController?.backgroundModel { if let background = listView.document.background() { KMBackgroundManager.defaultManager.updateBackground(background, withModel: model) background.pageString = pageString background.update() listView.document?.refreshPageData() listView.layoutDocumentView() } } exitEditToolbarView() } else if view.editType == .header_Footer { if let model = headerFooterViewController?.headerFooterModel { if let headerFooter = listView.document.headerFooter() { KMHeaderFooterManager.defaultManager.updateCPDFHeaderFooter(headerFooter, withModel: model, Int(listView.document.pageCount)) headerFooter.pageString = pageString headerFooter.update() listView.document?.refreshPageData() listView.layoutDocumentView() } } exitEditToolbarView() } else if view.editType == .bates { if let model = batesViewController?.batesModel { if let bates = listView.document.bates() { KMBatesManager.defaultManager.updateCPDFBates(bates, withModel: model, Int(listView.document.pageCount)) bates.pageString = pageString bates.update() listView.document?.refreshPageData() listView.layoutDocumentView() } } exitEditToolbarView() } } func kmEditToolbarViewDidChooseExit(_ view: KMEditToolbarView) { if view.applyEnable { let alert = NSAlert() if view.editType == .watermark { alert.messageText = NSLocalizedString("There are unapplied Watermark settings, do you want to apply them?", comment: "") } else if view.editType == .background { alert.messageText = NSLocalizedString("There are unapplied Background settings, do you want to apply them?", comment: "") } else if view.editType == .header_Footer { alert.messageText = NSLocalizedString("There are unapplied Header & Footer settings, do you want to apply them?", comment: "") } else if view.editType == .bates { alert.messageText = NSLocalizedString("There are unapplied Bates settings, do you want to apply them?", comment: "") } alert.informativeText = NSLocalizedString("If not, the changes will be lost.", comment: "") alert.addButton(withTitle: NSLocalizedString("Apply", comment: "")) alert.addButton(withTitle: NSLocalizedString("Don't Apply", comment: "")) alert.addButton(withTitle: NSLocalizedString("Cancel", comment: "")) let result = alert.runModal() if (result == .alertFirstButtonReturn) { self.kmEditToolbarViewDidChooseApply(view) } else if (result == .alertSecondButtonReturn) { //"Don't Apply" exitEditToolbarView() } else if (result == .alertThirdButtonReturn) { //Cancel } } else { exitEditToolbarView() } } } //MARK: - KMCropControllerDelegate 裁剪相关代理 extension KMMainViewController: KMCropControllerDelegate { func kmCropControllerDidCrop(_ controller: KMCropController, _ cropRect: CGRect, _ view: KMPageRangeSelectView) { let rangeSelectResult = view.getSelectedPageIndex(listView.document) let indexs = rangeSelectResult.0 let isCurrentPage = rangeSelectResult.1 var uIndexs: [UInt] = [] for index in indexs { if index > 0 { uIndexs.append(UInt(index-1)) } } if isCurrentPage { uIndexs = [UInt(listView.currentPageIndex)] } cropPages(atIndexs: uIndexs, to: [cropRect]) removeCropController() viewManager.subToolMode = .None if let toolbarVC = self.pdfToolbarController { toolbarVC.refreshSecondToolbarItemsState() self.kmPDFToolbarControllerDidToolbarItemClicked(toolbarVC, KMPDFToolbar_edit_crop_Identifier) } } func kmCropControllerDidCropSeparate(_ controller: KMCropController, _ view: KMPageRangeSelectView) { let rangeSelectResult = view.getSelectedPageIndex(listView.document) let indexs = rangeSelectResult.0 let isCurrentPage = rangeSelectResult.1 var rectArray: Array = [] var uIndexs: [UInt] = [] for index in indexs { if index > 0 { uIndexs.append(UInt(index-1)) let page = self.listView.document.page(at: UInt(index-1)) let rect = KMCropTools.getPageForegroundBox(page!) rectArray.append(rect) } } if isCurrentPage { uIndexs = [UInt(listView.currentPageIndex)] } cropPages(atIndexs: uIndexs, to: rectArray) removeCropController() viewManager.subToolMode = .None if let toolbarVC = self.pdfToolbarController { toolbarVC.refreshSecondToolbarItemsState() self.kmPDFToolbarControllerDidToolbarItemClicked(toolbarVC, KMPDFToolbar_edit_crop_Identifier) } } func kmCropControllerDidCropAuto(_ controller: KMCropController, _ view: KMPageRangeSelectView) { let rangeSelectResult = view.getSelectedPageIndex(listView.document) let indexs = rangeSelectResult.0 let isCurrentPage = rangeSelectResult.1 var uIndexs: [UInt] = [] for index in indexs { if index > 0 { uIndexs.append(UInt(index-1)) } } if isCurrentPage { uIndexs = [UInt(listView.currentPageIndex)] } auto_cropPagesWhiteMargin(uIndexs) removeCropController() viewManager.subToolMode = .None if let toolbarVC = self.pdfToolbarController { toolbarVC.refreshSecondToolbarItemsState() self.kmPDFToolbarControllerDidToolbarItemClicked(toolbarVC, KMPDFToolbar_edit_crop_Identifier) } } func kmCropControllerDidChangedSelectionOrMagnification(_ controller: KMCropController) { if let cropVC = rightSideController?.edit_cropController { if cropVC.pdfView != controller.pdfView { cropVC.pdfView = controller.pdfView } cropVC.cropSeparateOn = false cropVC.cropAutoOn = false cropVC.reloadData() } } } //MARK: - KMWatermarkControllerDelegate 水印相关代理 extension KMMainViewController: KMWatermarkControllerDelegate { func kmWatermarkControllerDidUpdateMode(_ view: KMWatermarkController) { editToolbarView?.editSubType = view.editSubType editToolbarView?.reloadData() } func kmWatermarkControllerDidWatermarkUpdated(_ view: KMWatermarkController) { var applyEnable = true if let model = view.currentWatermarkData { if model.watermarkType == .text { if model.text == nil || model.text?.count == 0 { applyEnable = false } } else if model.watermarkType == .image { if model.imagePath == nil { applyEnable = false } } } else { applyEnable = false } editToolbarView?.applyEnable = applyEnable editToolbarView?.reloadData() } } //MARK: - KMBackgroundControllerDelegate 背景代理 extension KMMainViewController: KMBackgroundControllerDelegate { func kmBackgroundControllerDidUpdateMode(_ view: KMBackgroundController) { editToolbarView?.editSubType = view.editSubType } func kmBackgroundControllerDidBGDataUpdated(_ view: KMBackgroundController) { var applyEnable = true if let model = view.backgroundModel { if model.type == .image { if model.imagePath == nil { applyEnable = false } } } else { applyEnable = false } editToolbarView?.applyEnable = applyEnable editToolbarView?.reloadData() } } //MARK: - KMHeaderFooterControllerDelegate 页眉页脚代理 extension KMMainViewController: KMHeaderFooterControllerDelegate { func kmHeaderFooterControllerDidUpdateModeType(_ view: KMHeaderFooterController) { editToolbarView?.editSubType = view.editSubType } func kmHeaderFooterControllerDidModelDataUpdated(_ view: KMHeaderFooterController) { var applyEnable = true if let model = view.headerFooterModel { if model.topLeftString.count == 0 && model.topCenterString.count == 0 && model.topRightString.count == 0 && model.bottomLeftString.count == 0 && model.bottomCenterString.count == 0 && model.bottomRightString.count == 0 { applyEnable = false } } else { applyEnable = false } editToolbarView?.applyEnable = applyEnable editToolbarView?.reloadData() } } //MARK: - KMBatesControllerDelegate Bates贝茨码代理 extension KMMainViewController: KMBatesControllerDelegate { func kmBatesControllerDidUpdateMode(_ view: KMBatesController) { editToolbarView?.editSubType = view.editSubType editToolbarView?.reloadData() } func kmBatesControllerDidModelDataUpdated(_ view: KMBatesController) { var applyEnable = true if let model = view.batesModel { if model.topLeftString.count == 0 && model.topCenterString.count == 0 && model.topRightString.count == 0 && model.bottomLeftString.count == 0 && model.bottomCenterString.count == 0 && model.bottomRightString.count == 0 { applyEnable = false } } else { applyEnable = false } editToolbarView?.applyEnable = applyEnable editToolbarView?.reloadData() } } //MARK: - CPDFViewDelegate PDFView代理 extension KMMainViewController: CPDFViewDelegate,CPDFListViewDelegate { func pdfViewDocumentDidLoaded(_ pdfView: CPDFView!) { sideBarController?.reloadPageTurnerData() documentLoadComplete() } func pdfViewCurrentPageDidChanged(_ pdfView: CPDFView!) { sideBarController?.reloadPageTurnerData() botaViewController?.currentPageDidChangedAction(listView: listView) //分屏视图 reloadPDFPageNumberToolbar() if viewManager.splitSyncScroll { if splitPDFController?.inPDFFirst == false && splitPDFController?.outPDFFirst == false { splitPDFController?.outPDFFirst = true if let splitPDFView = splitPDFController?.pdfView, let document = splitPDFView.document { var index = pdfView.currentPageIndex if index > document.pageCount { index = Int(splitPDFView.document.pageCount - 1) } splitPDFView.go(toPageIndex: index, animated: false) } NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(pdfUpdatedFinish), object: nil) self.perform(#selector(pdfUpdatedFinish), with: nil, afterDelay: 0.35) } else if splitPDFController?.outPDFFirst == true { if let splitPDFView = splitPDFController?.pdfView, let document = splitPDFView.document { var index = pdfView.currentPageIndex if index > document.pageCount { index = Int(splitPDFView.document.pageCount - 1) } splitPDFView.go(toPageIndex: index, animated: false) } NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(pdfUpdatedFinish), object: nil) self.perform(#selector(pdfUpdatedFinish), with: nil, afterDelay: 0.35) } } //水印 updateEditModeDocumentWhenPageChanged() // } func pdfViewScaleDidChanged(_ pdfView: CPDFView!) { pdfToolbarController?.reloadSelectZoomView() reloadPDFPageNumberToolbar() reloadPopUIWindow() //分屏视图 if viewManager.splitSyncScroll { if splitPDFController?.inPDFFirst == false && splitPDFController?.outPDFFirst == false { splitPDFController?.outPDFFirst = true NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(pdfUpdatedFinish), object: nil) self.perform(#selector(pdfUpdatedFinish), with: nil, afterDelay: 0.35) } else if splitPDFController?.outPDFFirst == true { if let splitPDFView = splitPDFController?.pdfView { splitPDFView.scaleFactor = pdfView.scaleFactor } NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(pdfUpdatedFinish), object: nil) self.perform(#selector(pdfUpdatedFinish), with: nil, afterDelay: 0.35) } } } func pdfViewDidClick(onLink pdfView: CPDFView!, withURL url: String!) { if let urlString = url, urlString == Store_Link { //跳转订阅比较表 return } if url.hasPrefix("smb://") { NSWorkspace.shared.openFile(url) } else { KMTools.openURL(urlString: url) } } func pdfViewPerformURL(_ pdfView: CPDFView!, withContent content: String!) { KMPrint("pdfViewPerformURL") if content != nil { NSWorkspace.shared.open(URL(string: content)!) } else { let alert = NSAlert() alert.alertStyle = .critical alert.informativeText = NSLocalizedString("The hyperlink is invalid.", comment: "") alert.messageText = "" alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } } func pdfViewPerformPrint(_ pdfView: CPDFView!) { KMPrint("pdfViewPerformPrint") self.showPrintWindow() } func pdfViewPerformGo(toPage pdfView: CPDFView!) { KMPrint("pdfViewPerformGo") } func pdfViewOpenPDF(_ pdfView: CPDFView!, forRemoteGoTo action: CPDFAction!) { KMPrint("pdfViewOpenPDF") } func pdfViewPerformReset(_ pdfView: CPDFView!) { KMPrint("pdfViewPerformReset") pdfView.document?.resetForm() } func pdfViewEditingBlockDidChanged(_ pdfView: CPDFView!) { KMPrint("pdfViewEditingBlockDidChanged") } func pdfViewAsBookBookmark() -> NSImage! { return NSImage(named: "KMImageNameBookmarkIcon")! } //MARK: -编辑模块 func pdfViewEditingSelectionDidChanged(_ pdfView: CPDFView!) { // 文本区块 选中文本已经变化 reloadPopUIWindow() } func pdfViewPDFSelectionAttributeDidChanged(_ pdfView: CPDFView!) { reloadPopUIWindow() } func pdfViewEditingAreaDidChanged(_ pdfView: CPDFView!) { //编辑模块变化 rightSideController?.reloadDataWithPDFView(pdfView: (pdfView as! CPDFListView)) if pdfView is CPDFListView { (pdfView as! CPDFListView).isEditImage = false } reloadPopUIWindow() } func pdfViewEditingCropBoundsDidChanged(_ pdfView: CPDFView!, editing editArea: CPDFEditArea!) { if editArea != nil && (editArea is CPDFEditImageArea){ self.listView.cropAreas = editArea as? CPDFEditImageArea } reloadPopUIWindow() } //编辑PDF 创建图片区域回调 func pdfViewEditingAddImageArea(_ pdfView: CPDFView!, add page: CPDFPage!, add rect: CGRect) { if (pdfView as! CPDFListView).isEditImage { return } if rect.size.width < 5 && rect.size.height < 5 { pdfView.updateEditing([]) return } let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.allowedFileTypes = ["png","jpg"] panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { var filePath = panel.url?.path let image = NSImage.init(contentsOf: panel.url!) //图片自适应范围 if image != nil { var imageRect = rect let imageSize = image!.size var previewSize = rect.size var isChangeSize = false if previewSize.width == 0 && previewSize.height == 0 { previewSize = CGSize(width: 500, height: 500) isChangeSize = true } var scale = min(previewSize.width / imageSize.width, previewSize.height / imageSize.height) if scale < 1 { // 大于 500 } else { let wh = max(imageSize.width, imageSize.height) if wh >= 72 { scale = min(scale, 1) } else { scale = min(72 / imageSize.width, 72 / imageSize.height) } } let newSize = CGSize(width: imageSize.width * scale, height: imageSize.height * scale) if isChangeSize { imageRect.origin.x = imageRect.origin.x - newSize.width / 2 imageRect.origin.y = imageRect.origin.y - newSize.height / 2 } else { imageRect.origin.x = imageRect.origin.x + imageRect.width / 2 - newSize.width / 2 imageRect.origin.y = imageRect.origin.y + imageRect.height / 2 - newSize.height / 2 } imageRect.size = newSize let limitWidth = 1920.0 if imageSize.width > limitWidth || imageSize.height > limitWidth { filePath = KMImageOptimization.needCompressImageLosslessly(image: image!, targetSize: CGSize(width: limitWidth, height: limitWidth), maxSizeInBytes: 1024 * 1024 * 5, targetCompression: 1.0) } //自适应page let pageRect = self.listView.currentPage().bounds ?? .zero if imageRect.width > pageRect.width || imageRect.height > pageRect.height { let pageScale = min(pageRect.width / imageSize.width, pageRect.height / imageSize.height) imageRect = CGRect(x: imageRect.origin.x, y: imageRect.origin.y, width: imageRect.width * pageScale, height: imageRect.height * pageScale) } if imageRect.origin.x < 0 { imageRect.origin.x = 5 } if imageRect.origin.y < 0 { imageRect.origin.y = 5 } if imageRect.origin.x + imageRect.width > pageRect.width || imageRect.origin.y + imageRect.height > pageRect.height { let offsetX = imageRect.origin.x + imageRect.width - pageRect.width let offsetY = imageRect.origin.y + imageRect.height - pageRect.height imageRect.origin.x = imageRect.origin.x - offsetX - 5 imageRect.origin.y = imageRect.origin.y - offsetY - 5 } DispatchQueue.main.async { self.listView.createImagePath(filePath, rect: imageRect, page: pdfView.currentPage()) } } } } } func pdfViewEditingAddTextArea(_ pdfView: CPDFView!, add page: CPDFPage!, add rect: CGRect) { if rect.size.width < 5 && rect.size.height < 5 { let areas = self.listView.km_EditingAreas() if let area = areas.last { if let data = area as? CPDFEditTextArea { if let str = data.editTextAreaString(), str.isEmpty { self.listView.remove(with: area) } else { self.listView.updateEditing([]) } } } return } var newRect = rect if rect.size.equalTo(.zero) { newRect = CGRect(x: rect.origin.x, y: rect.origin.y - 12, width: 20, height: 12) } else { newRect = CGRect(x: rect.origin.x, y: rect.origin.y + rect.size.height - 12, width: rect.size.width, height: 12) } let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .commonly) let fontSize = model.fontSize let fontColor = model.color let fontAlign = model.alignment NSColorPanel.shared.color = fontColor let attri = CEditAttributes() attri.cFont = CPDFFont(familyName: model.fontName, fontStyle: model.fontStyle) attri.fontColor = fontColor attri.alignment = fontAlign attri.isBold = model.bold attri.isItalic = model.italic self.listView.createStringBounds(newRect, with: attri, page: page) } func pdfViewMobileEditingBegan(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { rightSideController?.reloadEditingAreas() toggleClosePopUIWindow() } func pdfViewMobileEditingMove(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { rightSideController?.reloadEditingAreas() toggleClosePopUIWindow() } func pdfViewMobileEditingEnd(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { rightSideController?.reloadEditingAreas() reloadPopUIWindow() } func pdfViewEditingSelectCharDidChanged(_ pdfView: CPDFView!) { rightSideController?.reloadEditingAreas() reloadPopUIWindow() } func pdfViewEditingExitCropMode(_ pdfView: CPDFView!, forEditing editingArea: CPDFEditImageArea!) { rightSideController?.reloadEditingAreas() toggleClosePopUIWindow() } func pdfViewEditingOperationDidChanged(_ pdfView: CPDFView!) { let areas = self.listView.km_editingImageAreas() if areas.count == 1 { if let data = areas.first as? CPDFEditImageArea { let updating = self.listView.editAreaBoundUpdating if updating { self.listView.editAreaBoundUpdating = false } } } } func pdfViewEditingDoubleClick(_ pdfView: CPDFView!, imageArea editArea: CPDFEditArea!) { if(editArea.isImageArea()) { listView.cropAction() } } func pdfListViewKeyDownIsContinue(_ pdfListView: CPDFListView!, theEvent: NSEvent!) -> Bool { let command = theEvent.modifierFlags.contains(.command) let control = theEvent.modifierFlags.contains(.control) KMPrint(theEvent.keyCode) if self.listView.isEditing() == true { if control && theEvent.keyCode == 11 { // ctr + b self.listView.setEditingTextarea_Bold() rightSideController?.reloadEditingAreas() return false } else if control && theEvent.keyCode == 34 { // ctr +i self.listView.setEditingTextarea_Italic() rightSideController?.reloadEditingAreas() return false } else if theEvent.keyCode == 36 { // enter if self.listView.isCropMode { self.listView.cropComfirmAction() rightSideController?.reloadEditingAreas() return false } } else if theEvent.keyCode == 53 { // Cancel if self.listView.isCropMode { self.listView.cropCancelAction() rightSideController?.reloadEditingAreas() return false } } } if (theEvent.keyCode == 11 && command) { // command + B [添加书签] self.menuItemBookMarkClick_add(sender: NSMenuItem()) return false } else if (command && control && theEvent.keyCode == 14) { // command + control + E [注释 橡皮擦] return false } else if (theEvent.keyCode == 123) { // 向左 if(self.listView.isEditing() && !self.listView.isSelecteditAreaNotEdit()) { return false } else { if (self.pdfViewCanHorizontalScroll() == false && self.listView.canGoToPreviousPage()) { self.listView.goToPreviousPage(nil) return false } } } else if (theEvent.keyCode == 126) { // 向上 if(self.listView.isEditing() && !self.listView.isSelecteditAreaNotEdit()) { return false } else { if (self.listView.isContinousScroll()) { return true } if (self.pdfViewCanVerticalScroll() == false && self.listView.canGoToPreviousPage()) { self.listView.goToPreviousPage(nil) return false } } } else if (theEvent.keyCode == 124) { // 向右 if(self.listView.isEditing() && !self.listView.isSelecteditAreaNotEdit()) { return false } else { if (self.pdfViewCanHorizontalScroll() == false && self.listView.canGoToNextPage()) { self.listView.goToNextPage(nil) return false } } } else if (theEvent.keyCode == 125) { // 向下 if(self.listView.isEditing() && !self.listView.isSelecteditAreaNotEdit()) { return false } else { if (self.listView.isContinousScroll()) { return true } if (self.pdfViewCanVerticalScroll() == false && self.listView.canGoToNextPage()) { self.listView.goToNextPage(nil) return false } } } else if (theEvent.keyCode == 36) { if self.listView.shouAddEditAreaType() == .image || self.listView.shouAddEditAreaType() == .text { if self.listView.isEditImage { self.menuItemEditingClick_CropImage(sender: NSMenuItem()) } } } if theEvent.keyCode == 53 { //ESC self.exitFullScreen() if viewManager.isPDFReadMode { self.exitPDFReadMode() } self.leftSideViewCancelSelect() } return true } func pdfListViewMenuValidate(_ pdfListView: CPDFListView!, menuItem: NSMenuItem!, isTakesEffect: UnsafeMutablePointer!) -> Bool { guard let action = menuItem.action else { isTakesEffect.pointee = false return false } isTakesEffect.pointee = false return false } //MARK: - CPDFListViewDelegate func pdfListViewChangedToolMode(_ pdfListView: CPDFListView!, for toolMode: CToolMode) { reloadPopUIWindow() } func pdfListViewChangedAnnotationType(_ pdfListView: CPDFListView!, for annotationType: CAnnotationType) { if(annotationType == .unkown) { toggleCloseRightSide() } else if annotationType == .measureLine || annotationType == .measurePolyLine || annotationType == .measurePolyGon || annotationType == .measureSquare { refreshMeasureInfo() } } func pdfListViewChangeatioActiveAnnotations(_ pdfListView: CPDFListView!, forActiveAnnotations annotations: [CPDFAnnotation]!, isRightMenu: Bool) { self.view.window?.makeFirstResponder(self.listView) reloadPopUIWindow() if isRightMenu { } else if annotations.count > 0 { if self.viewManager.isPDFReadMode { toggleCloseRightSide() } else { let isMultiAnnotations = pdfListView.isMultiAnnotation(annotations) if isMultiAnnotations == true { viewManager.showRightSide = false } else { viewManager.showRightSide = true } refreshToolbarRightViewInfo() } } else if (annotations.count == 0){ if pdfListView.annotationType == .unkown { viewManager.showRightSide = false } else { if self.viewManager.isPDFReadMode { viewManager.showRightSide = false } else { viewManager.showRightSide = true } } refreshToolbarRightViewInfo() } self.refreshMeasureInfo() // pdfToolbarController?.pdfViewActiveAnnotationsChanged() } func pdfListViewMenu(forEvent pdfListView: CPDFListView!, for theEvent: NSEvent!, click menu: AutoreleasingUnsafeMutablePointer!, isMoveSelectAnno: Bool) { var pagePoint = CGPoint.zero let point = theEvent.locationInWindow let isShowPopUI:Bool = false if let page = pdfListView.pageAndPoint(&pagePoint, for: theEvent, nearest: false) { if view.window?.interactionMode == .presentation { let menuStruct = clickPresentationMenu(point: pagePoint) groupListMenuGroup?.groupDelegate = self groupListMenuGroup?.frame = CGRectMake(0, 0, 180, menuStruct.viewHeight) groupListMenuGroup?.updateGroupInfo(menuStruct.menuitems) groupListMenuGroup?.showWithPoint(CGPoint(x: point.x, y: point.y - menuStruct.viewHeight), relativeTo: pdfListView) } else { var menuStringArr: [String] = [] let activeAnnotations = pdfListView.activeAnnotations as? [CPDFAnnotation] if activeAnnotations?.count ?? 0 > 1 { var isSameAnnotation = true let firstAnnotation = activeAnnotations?.first for i in 1..<(activeAnnotations?.count ?? 1) { if firstAnnotation?.type != activeAnnotations?[i].type { isSameAnnotation = false break } } if isSameAnnotation { if firstAnnotation?.isKind(of: CPDFMarkupAnnotation.self) == true { menuStringArr.append(PDFViewMenuIdentifier_Normal_CopyText) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) } if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) menuStringArr.append(PDFViewMenuIdentifier_Space) } menuStringArr.append(PDFViewMenuIdentifier_Normal_SortAnnotation) if firstAnnotation?.isKind(of: CPDFLinkAnnotation.self) == true || firstAnnotation?.isKind(of: CPDFWidgetAnnotation.self) == true { menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Aligning) } } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_SortAnnotation) if firstAnnotation?.isKind(of: CPDFWidgetAnnotation.self) == true { menuStringArr.append(PDFViewMenuIdentifier_Normal_Aligning) } } } else if activeAnnotations?.count == 1 { if pdfListView.activeAnnotation.isKind(of: CPDFMarkupAnnotation.self) { menuStringArr.append(PDFViewMenuIdentifier_Normal_CopyText) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_SortAnnotation) } else if pdfListView.activeAnnotation.isKind(of: CPDFRedactAnnotation.self) { menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Redact_Apply) menuStringArr.append(PDFViewMenuIdentifier_Redact_Multipage) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_RedactProperties) menuStringArr.append(PDFViewMenuIdentifier_Redact_Default) } else if listView.activeAnnotation.isKind(of: CPDFLinkAnnotation.self) { let link = listView.activeAnnotation as? CPDFLinkAnnotation menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) if link?.destination() != nil || ((link?.url()) != nil) { menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_LinkReade) } if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } } else if pdfListView.activeAnnotation.isKind(of: CPDFWidgetAnnotation.self) { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) menuStringArr.append(PDFViewMenuIdentifier_Space) } menuStringArr.append(PDFViewMenuIdentifier_Normal_SortAnnotation) } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) if pdfListView.activeAnnotation.isKind(of: CPDFTextAnnotation.self) || pdfListView.activeAnnotation.isKind(of: CPDFFreeTextAnnotation.self) { } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Content) menuStringArr.append(PDFViewMenuIdentifier_Space) } if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) menuStringArr.append(PDFViewMenuIdentifier_Space) } menuStringArr.append(PDFViewMenuIdentifier_Normal_SortAnnotation) } } else { let currentSelection = pdfListView.currentSelection if currentSelection != nil { if currentSelection?.selectionType() == .text { menuStringArr.append(PDFViewMenuIdentifier_Normal_AITool) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) if pdfListView.canPaste() { menuStringArr.append(PDFViewMenuIdentifier_Normal_Past) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Hight) menuStringArr.append(PDFViewMenuIdentifier_Normal_Underline) menuStringArr.append(PDFViewMenuIdentifier_Normal_StrikeOut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Squiggly) menuStringArr.append(PDFViewMenuIdentifier_Normal_Square) menuStringArr.append(PDFViewMenuIdentifier_Normal_Circle) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddOutLine) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddBook) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_TTS) menuStringArr.append(PDFViewMenuIdentifier_Normal_SearchText) } else if currentSelection?.selectionType() == .image { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) if pdfListView.canPaste() { menuStringArr.append(PDFViewMenuIdentifier_Normal_Past) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Export) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Square) menuStringArr.append(PDFViewMenuIdentifier_Normal_Circle) } } else { if pdfListView.toolMode == .CFormToolMode { if pdfListView.canPaste() { menuStringArr.append(PDFViewMenuIdentifier_Normal_Past) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_SelectAllForm) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightForm) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowFormName) menuStringArr.append(PDFViewMenuIdentifier_Normal_RestForm) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddBook) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ViewTools) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageView) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Scale) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageRotate) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageNum) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Search) menuStringArr.append(PDFViewMenuIdentifier_Normal_Print) menuStringArr.append(PDFViewMenuIdentifier_Normal_Properties) } else if pdfListView.toolMode == .CRedactToolMode { menuStringArr.append(PDFViewMenuIdentifier_Normal_SelectAllText) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddBook) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ViewTools) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageView) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Scale) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageRotate) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageNum) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightLink) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightForm) menuStringArr.append(PDFViewMenuIdentifier_Normal_RestForm) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Search) menuStringArr.append(PDFViewMenuIdentifier_Normal_Print) menuStringArr.append(PDFViewMenuIdentifier_Normal_Properties) } else { if(listView.viewSplitMode != .disable) { menuStringArr.append(PDFViewMenuIdentifier_Split_ViewMode) menuStringArr.append(PDFViewMenuIdentifier_Split_Sync) menuStringArr.append(PDFViewMenuIdentifier_Split_ShowBar) menuStringArr.append(PDFViewMenuIdentifier_Space) } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_AITool) menuStringArr.append(PDFViewMenuIdentifier_Space) if pdfListView == listView { if pdfListView.canPaste() { menuStringArr.append(PDFViewMenuIdentifier_Normal_Past) } menuStringArr.append(PDFViewMenuIdentifier_Normal_SelectAllText) menuStringArr.append(PDFViewMenuIdentifier_Normal_SelectAllAnnotation) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowAnnotation) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddBook) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ViewTools) menuStringArr.append(PDFViewMenuIdentifier_Space) } } menuStringArr.append(PDFViewMenuIdentifier_Normal_PageView) if(listView.viewSplitMode != .disable) { } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_ReadMode) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Scale) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageRotate) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageNum) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AutoScroll) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightLink) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightForm) menuStringArr.append(PDFViewMenuIdentifier_Normal_RestForm) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Search) menuStringArr.append(PDFViewMenuIdentifier_Normal_Print) menuStringArr.append(PDFViewMenuIdentifier_Normal_Properties) } } } let menuStruct = KMPDFMenuConfig.clickMenuUI(items: menuStringArr, theEvent: theEvent, listView: pdfListView) groupListMenuGroup?.groupDelegate = self groupListMenuGroup?.frame = CGRectMake(0, 0, 180, menuStruct.viewHeight) groupListMenuGroup?.updateGroupInfo(menuStruct.menuitems) groupListMenuGroup?.showWithPoint(CGPoint(x: point.x, y: point.y - menuStruct.viewHeight), relativeTo: pdfListView) } } else { var menuStringArr: [String] = [] menuStringArr.append(PDFViewMenuIdentifier_Normal_PageView) menuStringArr.append(PDFViewMenuIdentifier_Normal_ReadMode) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Scale) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightLink) menuStringArr.append(PDFViewMenuIdentifier_Normal_HightForm) menuStringArr.append(PDFViewMenuIdentifier_Normal_RestForm) let menuStruct = KMPDFMenuConfig.clickMenuUI(items: menuStringArr, theEvent: theEvent, listView: pdfListView) groupListMenuGroup?.groupDelegate = self groupListMenuGroup?.frame = CGRectMake(0, 0, 180, menuStruct.viewHeight) groupListMenuGroup?.updateGroupInfo(menuStruct.menuitems) groupListMenuGroup?.showWithPoint(CGPoint(x: point.x, y: point.y - menuStruct.viewHeight), relativeTo: pdfListView) } reloadPopUIWindow() } func pdfListViewMenuItemsEditing(at point: CGPoint, for page: CPDFPage!, menuItems: [NSMenuItem]!) -> [NSMenuItem]! { var windowPoint = listView.convert(point, from: page) let view: NSView? = nil windowPoint = listView.convert(windowPoint, to: view) if self.view.window?.interactionMode == .presentation { let menuStruct = clickPresentationMenu(point: point) groupListMenuGroup?.groupDelegate = self groupListMenuGroup?.frame = CGRectMake(0, 0, 180, menuStruct.viewHeight) groupListMenuGroup?.updateGroupInfo(menuStruct.menuitems) groupListMenuGroup?.showWithPoint(CGPoint(x: windowPoint.x, y: windowPoint.y - menuStruct.viewHeight), relativeTo: listView) } else { let isShowPopUI:Bool = false var menuStringArr: [String] = [] let editingAreas = listView.km_EditingAreas() let firstEditingArea = editingAreas.first if editingAreas.count > 1 { var isSameEditingArea = true if(firstEditingArea?.isTextArea() == true) { for i in 1..<(editingAreas.count) { if !editingAreas[i].isTextArea() { isSameEditingArea = false break } } } else if (firstEditingArea?.isImageArea() == true) { for i in 1..<(editingAreas.count) { if !editingAreas[i].isImageArea() { isSameEditingArea = false break } } } if(isSameEditingArea) { if (firstEditingArea?.isTextArea() == true) { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) if listView.isSupportPastMatchStyle() { menuStringArr.append(PDFViewMenuIdentifier_Edit_Paste) } if listView.isSupportPast() { menuStringArr.append(PDFViewMenuIdentifier_Edit_NoStylePaste) } menuStringArr.append(PDFViewMenuIdentifier_Edit_SelectAll) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Edit_Font) menuStringArr.append(PDFViewMenuIdentifier_Edit_FontName) menuStringArr.append(PDFViewMenuIdentifier_Edit_FontAlight) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Aligning) } else if (firstEditingArea?.isImageArea() == true) { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Edit_RotateLeft) menuStringArr.append(PDFViewMenuIdentifier_Edit_RotateRight) menuStringArr.append(PDFViewMenuIdentifier_Edit_HorizontalMirror) menuStringArr.append(PDFViewMenuIdentifier_Edit_VerticalMirror) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Export) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Aligning) } } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Aligning) } } else if editingAreas.count == 1 { if firstEditingArea?.isTextArea() == true { if !listView.isSelecteditAreaNotEdit() { //光标输入状态 if listView.isSupportPast() { menuStringArr.append(PDFViewMenuIdentifier_Edit_NoStylePaste) } menuStringArr.append(PDFViewMenuIdentifier_Edit_SelectAll) menuStringArr.append(PDFViewMenuIdentifier_Space) } else { let editState = listView.editStatus() if (editState == .editSelectText) {// 选择文本 menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) if listView.isSupportPast() { menuStringArr.append(PDFViewMenuIdentifier_Edit_NoStylePaste) } menuStringArr.append(PDFViewMenuIdentifier_Edit_SelectAll) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) } else { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) if listView.isSupportPastMatchStyle() { menuStringArr.append(PDFViewMenuIdentifier_Edit_Paste) } if listView.isSupportPast() { menuStringArr.append(PDFViewMenuIdentifier_Edit_NoStylePaste) } menuStringArr.append(PDFViewMenuIdentifier_Edit_SelectAll) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) } menuStringArr.append(PDFViewMenuIdentifier_Edit_Font) menuStringArr.append(PDFViewMenuIdentifier_Edit_FontName) menuStringArr.append(PDFViewMenuIdentifier_Edit_FontAlight) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } } } else if firstEditingArea?.isImageArea() == true { menuStringArr.append(PDFViewMenuIdentifier_Normal_Copy) menuStringArr.append(PDFViewMenuIdentifier_Normal_Cut) menuStringArr.append(PDFViewMenuIdentifier_Normal_Delete) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Edit_RotateLeft) menuStringArr.append(PDFViewMenuIdentifier_Edit_RotateRight) menuStringArr.append(PDFViewMenuIdentifier_Edit_HorizontalMirror) menuStringArr.append(PDFViewMenuIdentifier_Edit_VerticalMirror) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Edit_Crop) menuStringArr.append(PDFViewMenuIdentifier_Edit_Replace) menuStringArr.append(PDFViewMenuIdentifier_Normal_Export) if(isShowPopUI){ menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ShowPopUI) } } } else { if(listView.isSupportPastMatchStyle()) { menuStringArr.append(PDFViewMenuIdentifier_Edit_Paste) } if(listView.isSupportPast()) { menuStringArr.append(PDFViewMenuIdentifier_Edit_NoStylePaste) } menuStringArr.append(PDFViewMenuIdentifier_Edit_SelectAll) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Edit_AddText) menuStringArr.append(PDFViewMenuIdentifier_Edit_AddImage) menuStringArr.append(PDFViewMenuIdentifier_Edit_AddLink) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_AddBook) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_ViewTools) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageView) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Scale) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageRotate) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_PageNum) menuStringArr.append(PDFViewMenuIdentifier_Space) menuStringArr.append(PDFViewMenuIdentifier_Normal_Search) menuStringArr.append(PDFViewMenuIdentifier_Normal_Print) menuStringArr.append(PDFViewMenuIdentifier_Normal_Properties) } let menuStruct = KMPDFMenuConfig.clickMenuUI(items: menuStringArr, theEvent: nil, listView: listView) groupListMenuGroup?.groupDelegate = self groupListMenuGroup?.frame = CGRectMake(0, 0, 180, menuStruct.viewHeight) groupListMenuGroup?.updateGroupInfo(menuStruct.menuitems) groupListMenuGroup?.showWithPoint(CGPoint(x: windowPoint.x, y: windowPoint.y - menuStruct.viewHeight), relativeTo: listView) } return [] } func pdfListViewMobileAnnotationBegan(_ point: CGPoint, for pdfListView: CPDFListView!, forActiveAnnotations annotations: [CPDFAnnotation]!) { toggleClosePopUIWindow() } func pdfListViewMobileAnnotationMove(_ point: CGPoint, for pdfListView: CPDFListView!, forActiveAnnotations annotations: [CPDFAnnotation]!) { toggleClosePopUIWindow() } func pdfListViewMobileAnnotationEnd(_ point: CGPoint, for pdfListView: CPDFListView!, forActiveAnnotations annotations: [CPDFAnnotation]!) { reloadPopUIWindow() } func pdfListViewAddAnnotations(_ pdfListView: CPDFListView!, forAdd annotations: [CPDFAnnotation]!, in pdfPage: CPDFPage!) { var pageIndexes = IndexSet() pageIndexes.insert(Int(pdfPage.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) botaViewController?.annoController.note_reloadDataIfNeed() } func pdfListViewRemoveAnnotations(_ pdfListView: CPDFListView!, forRemove annotations: [CPDFAnnotation]!, in pdfPage: CPDFPage!) { var pageIndexes = IndexSet() pageIndexes.insert(Int(pdfPage.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) botaViewController?.annoController.note_reloadDataIfNeed() } func pdfListViewEditAnnotation(_ pdfListView: CPDFListView!, for anotation: CPDFAnnotation!) { if anotation.isKind(of: CPDFSignatureWidgetAnnotation.self) { if let signatureWidgetAnnotation = anotation as? CPDFSignatureWidgetAnnotation { let signature = signatureWidgetAnnotation.signature() if ((signature) != nil) { popUpSignatureWidgetState(signature!, listView) } else { let widget = CPDFSignatureWidgetAnnotation.init(PDFListViewNoteWith: listView.document) widget.bounds = NSMakeRect(-1000, -1000, 545, 178); anotation.page.addAnnotation(widget) let configWindowVC = DSignatureConfigWindowController.init(windowNibName: "DSignatureConfigWindowController") configWindowVC.viewType = .fileList; configWindowVC.appearanceWidget = widget; configWindowVC.isCreatDS = false configWindowVC.complentionHandle = {[weak self] isSign, dic, config, isLock in widget.page.removeAnnotation(widget) if isSign { if (dic.object(forKey: SAVEFILEPATH_KEY) != nil) { let p12Path = dic.object(forKey: SAVEFILEPATH_KEY) as! String let password = dic.object(forKey: PASSWORD_KEY) if p12Path.count > 0 { self?.writeSignatureToWidget(signatureWidgetAnnotation, p12Path, password as! String, config, isLock) } } } else { if signatureWidgetAnnotation.isSignSignatureAdd() == true { self?.listView.remove(anotation) } } } configWindowVC.actionBlock = {[weak self] controller, type in if (type == .cancel) { NSApplication.shared.stopModal() controller.window?.orderOut(nil) controller.window?.close() widget.page.removeAnnotation(widget) if signatureWidgetAnnotation.isSignSignatureAdd() == true { self?.listView.remove(anotation) } else { self?.listView.setNeedsDisplayAnnotationViewFor(anotation.page) } } else if (type == .confirm) { NSApplication.shared.stopModal() controller.window?.orderOut(nil) controller.window?.close() } } configWindowVC.window?.center() NSApplication.shared.runModal(for: configWindowVC.window!) } } } else if anotation.isKind(of: CPDFRedactAnnotation.self) { if let redactAnnotation = anotation as? CPDFRedactAnnotation { let properties = KMRedactPropertiesWindowController() properties.readactAnnotation = redactAnnotation self.km_beginSheet(windowC: properties) properties.callback = { [weak self] annotation in if let page = annotation?.page { self?.listView.setNeedsDisplayAnnotationViewFor(page) } } } } } func pdfListViewSplitModeShowBar()->Bool { return viewManager.splitShowBottomBar } func pdfListViewEndEditMode(_ pdfListView: CPDFListView!) { let document = listView.document if(document != nil) { for i in 0.. [NSColor]! { if (annotation.isKind(of: CPDFMarkupAnnotation.self)) { if (annotation as! CPDFMarkupAnnotation).markupType() == .highlight { return KMAnnotationPropertiesColorManager.manager.markHighlightColors } else { return KMAnnotationPropertiesColorManager.manager.markOtherColors } } else { return KMAnnotationPropertiesColorManager.manager.markOtherColors } } func pdfListViewHaveDocumentAttribute() -> Bool { if(!self.listView.document.allowsCopying) { self.removeOwnerPassword() return false } return true } func pdfListViewShowTipView() -> Bool { let popWindow = KMNPopAnnotationWindowController.shared if popWindow.window?.isVisible == true { return true } return false } func pdfListViewAnnotationEditModeChange(_ pdfListView: CPDFListView!, for anotation: CPDFAnnotation!) { reloadPopUIWindow() } //MARK: -Measure func pdfListViewAnnotationMeasureInfoChange(_ pdfListView: CPDFListView!, with annotation: CPDFAnnotation!) { guard let data = annotation else { if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.clearData() } return } if let lineAnnotation = annotation as? CPDFLineAnnotation { handleLineAnnotation(lineAnnotation) } else if let polylineAnnotation = annotation as? CPDFPolylineAnnotation { handlePolylineAnnotation(polylineAnnotation) } else if let polygonAnnotation = annotation as? CPDFPolygonAnnotation { handlePolygonAnnotation(polygonAnnotation) } } func pdfListViewMeasureCancel(_ pdfListView: CPDFListView!) { cancelMeasureType() } private func handleLineAnnotation(_ annotation: CPDFLineAnnotation) { if perimeterMeasureInfoWindowController?.window?.isVisible == true { perimeterMeasureInfoWindowController?.hideFloatingWindow() distanceMeasureInfoWindowController?.showWindow(self) } else if areaMeasureInfoWindowController?.window?.isVisible == true { areaMeasureInfoWindowController?.hideFloatingWindow() distanceMeasureInfoWindowController?.showWindow(self) } else if distanceMeasureInfoWindowController?.window?.isVisible == false { distanceMeasureInfoWindowController?.showWindow(self) } let measureInfo = annotation.measureInfo let startPoint = annotation.startPoint let endPoint = annotation.endPoint let angle = atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x) * (180.0 / .pi) distanceMeasureInfoWindowController?.angleLabel.stringValue = String(format: "%.2f°", abs(angle)) distanceMeasureInfoWindowController?.xLabel.stringValue = String(format: "%.0f", abs(endPoint.x - startPoint.x)) distanceMeasureInfoWindowController?.yLabel.stringValue = String(format: "%.0f", abs(endPoint.y - startPoint.y)) distanceMeasureInfoWindowController?.reloadData(with: measureInfo!) } private func handlePolylineAnnotation(_ annotation: CPDFPolylineAnnotation) { if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.hideFloatingWindow() perimeterMeasureInfoWindowController?.showWindow(self) } else if areaMeasureInfoWindowController?.window?.isVisible == true { areaMeasureInfoWindowController?.hideFloatingWindow() perimeterMeasureInfoWindowController?.showWindow(self) } else if perimeterMeasureInfoWindowController?.window?.isVisible == false { perimeterMeasureInfoWindowController?.showWindow(self) } let measureInfo = annotation.measureInfo let savePoints = annotation.savePoints() var angle: CGFloat = 0 if savePoints.count >= 3 { let count = savePoints.count let startPoint = savePoints[count - 3].pointValue let midPoint = savePoints[count - 2].pointValue let endPoint = savePoints.last!.pointValue angle = angleBetweenPoints(startPoint, midPoint, endPoint) } angle = 180 - angle perimeterMeasureInfoWindowController?.angleLabel.stringValue = String(format: "%.2f°", abs(angle)) perimeterMeasureInfoWindowController?.reloadData(with: measureInfo!) } private func handlePolygonAnnotation(_ annotation: CPDFPolygonAnnotation) { if distanceMeasureInfoWindowController?.window?.isVisible == true { distanceMeasureInfoWindowController?.hideFloatingWindow() areaMeasureInfoWindowController?.showWindow(self) } else if perimeterMeasureInfoWindowController?.window?.isVisible == true { perimeterMeasureInfoWindowController?.hideFloatingWindow() areaMeasureInfoWindowController?.showWindow(self) } else if areaMeasureInfoWindowController?.window?.isVisible == false { areaMeasureInfoWindowController?.showWindow(self) } let measureInfo = annotation.measureInfo let savePoints = annotation.savePoints var angle: CGFloat = 0 if savePoints.count >= 3 { let count = savePoints.count let startPoint = (savePoints[count - 3] as AnyObject).pointValue let midPoint = (savePoints[count - 2] as AnyObject).pointValue let endPoint = (savePoints.lastObject as AnyObject).pointValue angle = angleBetweenPoints(startPoint!, midPoint!, endPoint!) } angle = 180 - angle areaMeasureInfoWindowController?.angleLabel.stringValue = String(format: "%.2f°", abs(angle)) areaMeasureInfoWindowController?.reloadData(measureInfo!) } private func angleBetweenPoints(_ startPoint: CGPoint, _ midPoint: CGPoint, _ endPoint: CGPoint) -> CGFloat { let vector1 = CGPoint(x: midPoint.x - startPoint.x, y: midPoint.y - startPoint.y) let vector2 = CGPoint(x: endPoint.x - midPoint.x, y: endPoint.y - midPoint.y) let dotProduct = vector1.x * vector2.x + vector1.y * vector2.y let magnitude1 = sqrt(vector1.x * vector1.x + vector1.y * vector1.y) let magnitude2 = sqrt(vector2.x * vector2.x + vector2.y * vector2.y) return acos(dotProduct / (magnitude1 * magnitude2)) * (180.0 / .pi) } @objc func pdfUpdatedFinish() { splitPDFController?.inPDFFirst = false splitPDFController?.outPDFFirst = false } //MARK: - Notification @objc private func pdfViewScrollViewDidScroll(_ noti: Notification) { reloadPopUIWindow() if listView.popOver?.isShown == true { listView.popOver?.close() } } func pageCountChangedNotification(_ sender: Notification) { guard let document = sender.object as? CPDFDocument else { return } botaViewController?.pageCountChangedAction(document: document) } func annotationsAttributeHasChange(_ sender: Notification) { guard let dict = sender.object as? [String : Any] else { return } if let anno = dict["object"] as? CPDFAnnotation { let value = dict["keyPath"] as? String ?? "" let didEnd = dict["didEnd"] as? Bool ?? false if didEnd { if value == CPDFAnnotationBoundsKey { if anno is CPDFSquareAnnotation || anno is CPDFCircleAnnotation { anno.contents = anno.page?.string(for: anno.bounds) ?? "" } } if anno.km_isMeasure() && anno.contents == nil { anno.contents = anno.string() ?? "" } var pageIndexes = IndexSet() pageIndexes.insert(Int(anno.page.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) botaViewController?.annoController.note_reloadDataIfNeed() reloadPopUIWindow() } else { if value != CPDFAnnotationBoundsKey && value != CPDFAnnotationStartPointKey && value != CPDFAnnotationEndPointKey && value != CPDFAnnotationPathsKey { // 改变bounds(箭头、直线注释 开始点和结束点, 手绘注释的paths)的操作会卡顿,比如移动 var pageIndexes = IndexSet() pageIndexes.insert(Int(anno.page.pageIndex())) botaViewController?.thumnailViewController?.reloadDataWithIndexs(pageIndexs: pageIndexes) botaViewController?.annoController.note_reloadDataIfNeed() reloadPopUIWindow() } } } } @objc fileprivate func signatureStateChangeNoti(_ sender: Notification) { guard let objecListView = sender.object as? CPDFListView else { return } if listView == objecListView { reloadDigitalSigns() alertTipViewController.reloadDigitalAlertUI() alertTipViewController.reloadAlertUIFrame() let signatureWidget = listView.editAnnotation if let signatureWidgetAnnotation = signatureWidget as? CPDFSignatureWidgetAnnotation { let signature = signatureWidgetAnnotation.signature() if signature == nil { return } signaturestateVC.signature = signature signaturestateVC.reloadData() } } } //MARK: - Mouse Event override func mouseMoved(with event: NSEvent) { self.view.window?.mouseMoved(with: event) } } //MARK: - KMNThumbnailBaseViewDelegate extension KMMainViewController: KMNThumbnailBaseViewDelegate { func clickThumbnailViewControlle(pageEditVC:KMNThumbnailBaseViewController?,currentIndex:Int) { exitPageEditMode() if listView.currentPageIndex != currentIndex { listView.go(toPageIndex: currentIndex, animated: true) } viewManager.isPageEditMode = false pdfToolbarController?.clickWithIdentify(KMPDFToolbar_PageEdit_Identifier) } func insertPDFThumbnailViewControlle(pageEditVC: KMNThumbnailBaseViewController?, pdfDocment: CPDFDocument?) { if(pdfDocment != nil) { insertDocuments.insert(pdfDocment!) } } func changeIndexPathsThumbnailViewControlle(pageEditVC: KMNThumbnailBaseViewController?, selectionIndexPaths: Set, selectionStrings: String) { toolbarManager.page_pageInfo_Property.text = selectionStrings if(toolbarManager.page_pageInfo_Property.creatable == false) { toolbarManager.page_pageInfo_Property.creatable = true } pdfToolbarController?.refreshSecondToolbarItemsState() } } //MARK: - KMNLeftSideViewControllerDelegate extension KMMainViewController: KMNLeftSideViewControllerDelegate { func enterPageEditLeftSideViewController(leftSideViewController: KMNLeftSideViewController) { if viewManager.isPageEditMode == false { viewManager.isPageEditMode = true if(pdfToolbarController != nil) { kmPDFToolbarControllerDidToolbarItemClicked(pdfToolbarController!, KMPDFToolbar_PageEdit_Identifier) pdfToolbarController?.reloadSecondToolbar() } } } func changeSelectePageLeftSideViewController(leftSideViewController: KMNLeftSideViewController, pageIndex: Int) { if(listView.currentPageIndex != pageIndex) { listView.go(toPageIndex: pageIndex, animated: true) } } func addBookmarkForLeftC(controller: KMNLeftSideViewController, bookmark: CPDFBookmark?, info: [String : Any]?) { if let result = info?["result"] as? Bool { if result == false { if let targetV = listView.superview { _ = KMNCustomAlertView.alertView(message: KMLocalizedString("This page has been bookmarked"), type: .normal_custom, fromView: targetV, point:CGPointMake(targetV.frame.size.width/2, targetV.bounds.size.height-24)) } } } } func switchSearchPopWindow(controller: KMNLeftSideViewController) { if(viewManager.pdfSideBarType == .search) { toggleCloseLeftSide() } let handdler = controller.searchViewC.handdler showSearchPopWindow(type: handdler.type, keyborad: handdler.searchKey, replaceText: handdler.replaceKey, results: handdler.searchResults) } func searchTypeDidChange(controller: KMNLeftSideViewController) { let handdler = controller.searchViewC.handdler if handdler.type == .replace { viewManager.toolMode = .Edit updatePDFViewAnnotationMode() } } } //MARK: - ComponentGroupDelegate extension KMMainViewController: ComponentGroupDelegate { func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) { if menuItemProperty?.identifier == PDFViewMenuIdentifier_PageNext { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if objectListView.canGoToNextPage() { objectListView.goToNextPage(nil) } } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_PagePrevious) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if objectListView.canGoToPreviousPage() { objectListView.goToPreviousPage(nil) } } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_PageFirst) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if objectListView.canGoToFirstPage() { objectListView.goToFirstPage(nil) } } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_PageLast) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if objectListView.canGoToLastPage() { objectListView.goToLastPage(nil) } } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Presentation_LaserPoint) { listView.exitPresentationDrawMode() } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Presentation_Brush) { listView.enterPresentationDrawMode() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Presentation_Exit) { self.exitFullScreen() } else if menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AIRewrite { viewManager.pdfSideBarType = .aiTools sideBarController?.reloadData() if let sideVC = sideBarController { kmPDFSideBarControllerDidSidebarTypeUpdated(sideVC) } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AIProofread) { viewManager.pdfSideBarType = .aiTools sideBarController?.reloadData() if let sideVC = sideBarController { kmPDFSideBarControllerDidSidebarTypeUpdated(sideVC) } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AITranslate) { viewManager.pdfSideBarType = .aiTools sideBarController?.reloadData() if let sideVC = sideBarController { kmPDFSideBarControllerDidSidebarTypeUpdated(sideVC) } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Past) { let theEvent = menuItemProperty?.representedObject if let currentEvent = theEvent as? NSEvent { var pagePoint = CGPoint.zero if let page = listView.pageAndPoint(&pagePoint, for: currentEvent, nearest: false) { listView.menuPointPaste(pagePoint, page: page, isRightPaste: true) } } } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SelectAllText) { listView.selectAll(nil) } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AddBook) { menuItemBookMarkClick_add(sender: nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_TextTool) { listView.toolMode = .CTextToolMode listView.annotationType = .unkown viewManager.viewToolsType = .Select pdfToolbarController?.reloadToolsView() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_MoveTool) { listView.toolMode = .CMoveToolMode listView.annotationType = .unkown viewManager.viewToolsType = .Scroll pdfToolbarController?.reloadToolsView() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SelectTool) { listView.toolMode = .CSelectToolMode listView.annotationType = .unkown viewManager.viewToolsType = .Content_Selection pdfToolbarController?.reloadToolsView() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_MagnifyTool) { listView.toolMode = .CMagnifyToolMode listView.annotationType = .unkown viewManager.viewToolsType = .Magnify pdfToolbarController?.reloadToolsView() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SelectZoomTool) { listView.toolMode = .CSelectZoomToolMode listView.annotationType = .unkown viewManager.viewToolsType = .AreaZoom pdfToolbarController?.reloadToolsView() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Single) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.menuItemClick_SinglePage(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SingleContinuous) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.menuItemClick_SinglePagesContinuous(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_TwoPages) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.menuItemClick_TwoPages(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_TwoPagesContinuous) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.menuItemClick_TwoPagesContinuous(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_BookMode) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.menuItemClick_BookMode(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ReadMode) { openPDFReadMode() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ScaleWidth) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { objectListView.autoScales = true } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ScalePage) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { let pageHeight = objectListView.currentPage()!.size.height let pdfviewHeight = objectListView.bounds.size.height objectListView.scaleFactor = pdfviewHeight/pageHeight objectListView.autoScales = false } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ScaleOrg) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if objectListView.scaleFactor != 1.0 { objectListView.scaleFactor = 1.0 objectListView.autoScales = false } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ScaleZoomIn) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { var scale = objectListView.scaleFactor 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 } objectListView.scaleFactor = scale } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ScaleZoomOut) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { var scale = objectListView.scaleFactor 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 } objectListView.scaleFactor = scale } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_RotateLeft) { if let dic = menuItemProperty?.representedObject as? NSDictionary { let objectListView = dic["Object"] as? CPDFListView let theEvent = dic["theEvent"] as? NSEvent if(objectListView != nil && theEvent != nil) { var pagePoint = CGPoint.zero if let page = objectListView?.pageAndPoint(&pagePoint, for: theEvent, nearest: false) { rotateLeft(page: page, listView: objectListView) } } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_RotateRight) { if let dic = menuItemProperty?.representedObject as? NSDictionary { let objectListView = dic["Object"] as? CPDFListView let theEvent = dic["theEvent"] as? NSEvent if(objectListView != nil && theEvent != nil) { var pagePoint = CGPoint.zero if let page = objectListView?.pageAndPoint(&pagePoint, for: theEvent, nearest: false) { rotateRight(page: page, listView: objectListView) } } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_EnterPageNum) { sideBarController?.beginEditing() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_PageBack) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if(objectListView.canGoBack() == true) { objectListView.goBack(nil) } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_PageForward) { if let objectListView = menuItemProperty?.representedObject as? CPDFListView { if(objectListView.canGoForward() == true) { objectListView.goForward(nil) } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AutoScroll) { toggleAutoFlow(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_HightForm) { highlightFormFiled(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_HightLink) { highlightLinks(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_RestForm) { resetForm(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Search) { if botaViewController != nil { switchSearchPopWindow(controller: botaViewController!) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Print) { menuItemAction_print(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Properties) { menuItemAction_property(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Copy) { if(listView.isEditing() == true) { listView.copyEditAreaAction() } else { listView.copy(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Hight) { if let currentSelect = listView.currentSelection { if(currentSelect.selectionType() == .text) { listView.addAnnotation(with: .highlight, selection: currentSelect, page: currentSelect.page, bounds: currentSelect.bounds) listView.currentSelection = nil; } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Underline) { if let currentSelect = listView.currentSelection { if(currentSelect.selectionType() == .text) { listView.addAnnotation(with: .underline, selection: currentSelect, page: currentSelect.page, bounds: currentSelect.bounds) listView.currentSelection = nil; } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Squiggly) { if let currentSelect = listView.currentSelection { if(currentSelect.selectionType() == .text) { listView.addAnnotation(with: .squiggly, selection: currentSelect, page: currentSelect.page, bounds: currentSelect.bounds) listView.currentSelection = nil; } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_StrikeOut) { if let currentSelect = listView.currentSelection { if(currentSelect.selectionType() == .text) { listView.addAnnotation(with: .strikeOut, selection: currentSelect, page: currentSelect.page, bounds: currentSelect.bounds) listView.currentSelection = nil; } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Square) { if let currentSelect = listView.currentSelection { listView.addAnnotation(with: .square, selection: currentSelect, page: currentSelect.page, bounds: currentSelect.bounds) listView.currentSelection = nil; } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Circle) { if let currentSelect = listView.currentSelection { listView.addAnnotation(with: .circle, selection: currentSelect, page: currentSelect.page, bounds: listView.currentSelection.bounds) listView.currentSelection = nil; } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_AddOutLine) { addOutLineItemAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_TTS) { startSpeaking(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SearchText) { searchBaiduAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SelectAllForm) { selectAllFormAnnotation() listView.setNeedsDisplayForVisiblePages() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ShowFormName) { listView.showFormFieldName = true listView.setNeedsDisplayForVisiblePages() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SelectAllAnnotation) { selectAllNomerAnnotation() listView.setNeedsDisplayForVisiblePages() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ShowAnnotation) { let isHiden = listView.hideNotes listView.hideNotes = !isHiden listView.setNeedsDisplayForVisiblePages() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_CopyText) { var copyText:String = "" let annotations = listView.activeAnnotations for i in 0 ..< (annotations?.count ?? 0){ if let an = annotations?[i] as? CPDFMarkupAnnotation { let markupContent = an.markupContent() if markupContent.isEmpty == false { if copyText.isEmpty == true { copyText = markupContent } else { copyText = "\n" + markupContent } } } } let pboard = NSPasteboard.general if copyText.isEmpty == false { pboard.clearContents() pboard.writeObjects([copyText as NSPasteboardWriting]) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Cut) { if(listView.isEditing() == true) { listView.cutEditAreaAction() } else { listView.cut(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Delete) { if(listView.isEditing() == true) { listView.remove(with: listView.km_EditingAreas()) } else { listView.delete(nil) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ShowPopUI) { reloadPopUIWindow() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_LinkReade) { } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SortFirstAnnotation) { listView.menuItemClick_BringFront(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SortTopAnnotation) { listView.menuItemClick_BringForward(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SortBottomAnnotation) { listView.menuItemClick_SendBackward(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_SortLastAnnotation) { listView.menuItemClick_SendBack(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_Content) { if let activeAnnotation = listView.activeAnnotation { listView.edit(activeAnnotation) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Redact_Apply) { redactApplyAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Redact_Multipage) { if let redactAnnotation = listView.activeAnnotation as? CPDFRedactAnnotation { redactMultipageAction(redactAnnotation: redactAnnotation) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Redact_Default) { if let redactAnnotation = listView.activeAnnotation as? CPDFRedactAnnotation { setPropertiesDefault(annotation: redactAnnotation) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Split_ViewSingleMode) { listView.viewSplitMode = .disable reloadPDFSplitInfo() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Split_ViewVerticalMode) { listView.viewSplitMode = .vertical reloadPDFSplitInfo() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Split_ViewHorizontalMode) { listView.viewSplitMode = .horizontal reloadPDFSplitInfo() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Split_Sync) { viewManager.splitSyncScroll = !viewManager.splitSyncScroll } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Split_ShowBar) { viewManager.splitShowBottomBar = !viewManager.splitShowBottomBar splitPDFController?.refreshToolbarState() reloadPDFPageNumberToolbar() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_LeftAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.left) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .left) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_VerticallyAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.vertical) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .vertical) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_RightAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.right) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .right) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_TopAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.top) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .top) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_HorizontallyAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.horizontally) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .horizontally) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_BottomAlight) { if(listView.isEditing()) { listView.changeEditingAreas(.bottom) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .bottom) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_DistributeHorizontally) { if(listView.isEditing()) { listView.changeEditingAreas(.disHorizontally) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .disHorizontally) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_DistributeVertically) { if(listView.isEditing()) { listView.changeEditingAreas(.disVertical) } else { listView.change(listView.activeAnnotations as? [CPDFAnnotation], alignmentType: .disVertical) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ExportJPG) { if(listView.isEditing() == true) { listView.exportEditingImageAreasAction(format: "jpg") } else { if let currentSelection = listView.currentSelection { if(currentSelection.selectionType() == .image) { listView.exprotSelection(currentSelection, type: 1) } } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ExportPNG) { if(listView.isEditing() == true) { listView.exportEditingImageAreasAction(format: "png") } else { if let currentSelection = listView.currentSelection { if(currentSelection.selectionType() == .image) { listView.exprotSelection(currentSelection, type: 0) } } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_ExportPDF) { if(listView.isEditing() == true) { listView.exportEditingImageAreasAction(format: "pdf") } else { if let currentSelection = listView.currentSelection { if(currentSelection.selectionType() == .image) { listView.exprotSelection(currentSelection, type: 2) } } } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_Paste) { listView.pasteEditAreaMatchStyleAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_NoStylePaste) { listView.pasteEditAreaAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_SelectAll) { if listView.km_EditingAreas().count <= 0 { listView.selectAllAreaAction() } else { listView.selectAllAction(with: listView.km_EditingAreas().first) } } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_AddLink) { pdfToolbarController?.clickWithIdentify(KMPDFToolbar_edit_link_Identifier) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_AddText) { pdfToolbarController?.clickWithIdentify(KMPDFToolbar_edit_text_Identifier) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_AddImage) { pdfToolbarController?.clickWithIdentify(KMPDFToolbar_edit_image_Identifier) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontBold) { listView.setEditingTextarea_Bold() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontItalic) { listView.setEditingTextarea_Italic() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontUnderline) { listView.setEditingTextarea_Under() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontStrikeout) { listView.setEditingTextarea_Strikeout() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontZoomIn) { listView.zoomInEditTextFontSize() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontZoomOut) { listView.zoomInEditTextFontSize() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontColor) { let colorPanel = NSColorPanel.shared colorPanel.setTarget(self) colorPanel.setAction(#selector(editFontColorItemPanelAction(_:))) colorPanel.orderFront(nil) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontH1Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .h1) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontH2Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .h2) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontH3Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .h3) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontB1Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .b1) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontB2Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .b2) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontB3Name) { let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .b3) self.updateEditPDFTextFontModel(model) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontLeftAlight) { listView.setEditingTextarea_Alignment(align:.left) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontCenterAlight) { listView.setEditingTextarea_Alignment(align:.center) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontRightAlight) { listView.setEditingTextarea_Alignment(align:.right) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_FontJustAlight) { listView.setEditingTextarea_Alignment(align:.justified) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_RotateLeft) { listView.rotateEditingAreas(90) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_RotateRight) { listView.rotateEditingAreas(-90) } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_HorizontalMirror) { listView.reverseYAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_VerticalMirror) { listView.reverseXAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_Crop) { listView.cropAction() } else if(menuItemProperty?.identifier == PDFViewMenuIdentifier_Edit_Replace) { listView.replaceImageEdit() } else if (menuItemProperty?.identifier == PDFViewMenuIdentifier_Normal_RedactProperties) { if let redactAnnotation = listView.activeAnnotation as? CPDFRedactAnnotation{ showRedactProperty(readactAnnotation: redactAnnotation) } } } func componentGroupDidDismiss(group: ComponentGroup?) { } func updateEditPDFTextFontModel(_ model: KMEditPDFTextFontModel) { let fontName = model.fontName let fontStyle = model.fontStyle let fontSize = model.fontSize let bold = model.bold let italic = model.italic let alignment = model.alignment let font = CPDFFont(familyName: fontName, fontStyle: fontStyle) listView.setEditingTextarea_font(font: font) listView.setEditingTextarea_FontSize(size: fontSize) listView.setEditingTextarea(isBold: bold) listView.setEditingTextarea(isItalic: italic) listView.setEditingTextarea_Alignment(align: alignment) } } // MARK: - KMSnapshotWindowControllerDelegate extension KMMainViewController: KMSnapshotWindowControllerDelegate { func snapshotControllerWillClose(_ controller: KMSnapshotWindowController) { } func snapshotController(_ controller: KMSnapshotWindowController, miniaturizedRect isMiniaturize: Bool) -> NSRect { return CGRectZero } func snapshotControllerDidFinishSetup(_ controller: KMSnapshotWindowController) { } } // MARK: - CPDFDocumentDelegate extension KMMainViewController: CPDFDocumentDelegate { func documentDidBeginDocumentFind(_ document: CPDFDocument!) { } func documentDidEndDocumentFind(_ document: CPDFDocument!) { } } // MARK: - 测量代理CDistanceSettingWindowControllerDelegate extension KMMainViewController : CDistanceSettingWindowControllerDelegate { func distanceSettingWindowController(_ distanceSettingWindowController: CDistanceSettingWindowController, updateMeasureInfo measureInfo: CPDFMeasureInfo?) { if measureInfo != nil { if self.listView.activeAnnotations.count > 0 { if self.listView.activeAnnotation.isKind(of: CPDFPolylineAnnotation.self) { self.updateMeasureInfo((self.listView.activeAnnotation as! CPDFPolylineAnnotation).measureInfo, withNewMeasure: measureInfo) } else if self.listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) { self.updateMeasureInfo((self.listView.activeAnnotation as! CPDFPolygonAnnotation).measureInfo, withNewMeasure: measureInfo) } else if let data = self.listView.activeAnnotation as? CPDFLineAnnotation, data.isMeasure { self.updateMeasureInfo(data.measureInfo, withNewMeasure: measureInfo) } self.listView.setNeedsDisplayAnnotationViewFor(self.listView.activeAnnotation.page) } self.updateMeasureInfo(self.listView.distanceMeasureInfo, withNewMeasure: measureInfo) self.updateMeasureInfo(self.listView.perimeterMeasureInfo, withNewMeasure: measureInfo) self.updateMeasureInfo(self.listView.polygonAreaMeasureInfo, withNewMeasure: measureInfo) self.updateMeasureInfo(self.listView.squareAreaMeasureInfo, withNewMeasure: measureInfo) } } func updateMeasureInfo(_ measureInfo: CPDFMeasureInfo?, withNewMeasure newMeasure: CPDFMeasureInfo?) { guard let measureInfo = measureInfo else { return } guard let newMeasure = newMeasure else { return } measureInfo.rulerBase = newMeasure.rulerBase measureInfo.rulerTranslate = newMeasure.rulerTranslate measureInfo.rulerBaseUnit = newMeasure.rulerBaseUnit measureInfo.rulerTranslateUnit = newMeasure.rulerTranslateUnit measureInfo.factor = newMeasure.factor measureInfo.precision = newMeasure.precision } } //MARK: - extension extension KMMainViewController { internal func removeNotifications() { NotificationCenter.default.removeObserver(self) } func removeAllAnnotations() { let alert = NSAlert() alert.messageText = NSLocalizedString("This will permanently remove all annotations. Are you sure to continue?", comment: "") alert.addButton(withTitle: NSLocalizedString("Yes", comment:"")) alert.addButton(withTitle: NSLocalizedString("No", comment:"")) if (alert.runModal() != .alertFirstButtonReturn) { return } DispatchQueue.main.async { self.removeAllAnnotationsStore.store(t: self.listView) } } //MARK: - AI func showAITypeChooseView(aiConfigType: AIConfigType) -> Void { if (self.document != nil) { AIChatInfoManager.defaultManager.currentFilePath = (self.document?.documentURL.path)! } else { AIChatInfoManager.defaultManager.currentFilePath = "" } let windowVC: AINewConfigWindowController = AINewConfigWindowController.currentWC() windowVC.chooseCurFileHandle = {[unowned self] windowVC in if AIChatInfoManager.defaultManager.currentFilePath.isEmpty == false { let documentArray = NSDocumentController.shared.documents var didFileEdit: Bool = false var curDoc: KMMainDocument! for document in documentArray { if document.fileURL?.path == AIChatInfoManager.defaultManager.currentFilePath { didFileEdit = document.isDocumentEdited curDoc = document as! KMMainDocument break } } if didFileEdit { let tempFileURL = FileManager.default.temporaryDirectory.appendingPathComponent(AIChatInfoManager.defaultManager.currentFilePath.lastPathComponent) if FileManager.default.fileExists(atPath: tempFileURL.path) { do { try FileManager.default.removeItem(at: tempFileURL) } catch { } } if curDoc != nil { curDoc.mainViewController?.SaveTempPDFDocumentToURLPath(tempPath: tempFileURL.path) } } windowVC.window?.becomeMain() } } if windowVC.window?.isVisible == true && windowVC.didSetOriginFrame == true { } else { var windowRect = windowVC.window?.frame windowRect!.origin.x = NSMaxX(self.view.window!.frame) - (windowRect?.size.width)! windowRect!.origin.y = NSMaxY(self.view.window!.frame) - (windowRect?.size.height)! - 64 windowVC.window?.setFrame(windowRect!, display: true) windowVC.didSetOriginFrame = true } windowVC.eventLabel = "AITools_Tbr" windowVC.showWindow(nil) if (aiConfigType != .none) { windowVC.eventLabel = "AITools_Start" if self.listView.currentSelection?.string()?.isEmpty == false { windowVC.setCurrentPDFSelection(self.listView.currentSelection.string()) } windowVC.chooseAIFunctionWithType(aiConfigType) } } @objc func aiTipIconViewShowStateChangeNoti() { } //MARK: - 引导 func loadFunctionGuide() -> Void { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { if self.view.window != nil { self.loadOpenFileFunctionGuide(.openFileNormal) } } } func loadOpenFileFunctionGuide(_ showType: KMGuideInfoType) -> Void { if showType == .openFileNormal && KMGuideInfoWindowController.availableShow(.openFileNormal) { self.guideInfoWindowController = KMGuideInfoWindowController.currentWC() guard let guideWC = self.guideInfoWindowController else { return } guideWC.type = .openFileNormal // guideWC.openPanelRect = (self.view.window?.contentView?.convert(leftPanelItem.frame, from: leftPanelItem.superview)) ?? .zero guideWC.window?.collectionBehavior = [.canJoinAllSpaces] guideWC.normalGuideFinishHandle = { [weak self] windowVC in } guideWC.finishHandle = { [weak self] windowVC, type in if type == .windowNewFinish || type == . windowDigitalFinish { self?.checkFirstTrialController() } } guideWC.openFileToggleHandle = { [weak self] windowVC, type in self?.checkFirstTrialController() } var rect = self.view.window!.frame rect.size.height -= 20 guideWC.window?.setFrame(rect, display: false) guideWC.window?.minSize = rect.size guideWC.window?.maxSize = rect.size self.view.window?.addChildWindow(guideWC.window!, ordered: .above) guideWC.show() } else if showType == .digitalSignGuide && KMGuideInfoWindowController.availableShow(.digitalSignGuide) { self.guideInfoWindowController = KMGuideInfoWindowController.currentWC() guard let guideWC = self.guideInfoWindowController else { return } guideWC.type = .digitalSignGuide guideWC.window?.collectionBehavior = [.canJoinAllSpaces] guideWC.finishHandle = { [weak self] windowVC, type in self?.checkFirstTrialController() } var rect = self.view.window!.frame rect.size.height -= 20 guideWC.window?.setFrame(rect, display: false) guideWC.window?.minSize = rect.size guideWC.window?.maxSize = rect.size self.view.window?.addChildWindow(guideWC.window!, ordered: .above) guideWC.show() } else if showType == .pdfCompareGuide && KMGuideInfoWindowController.availableShow(.pdfCompareGuide) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { self.guideInfoWindowController = KMGuideInfoWindowController.currentWC() guard let guideWC = self.guideInfoWindowController else { return } guideWC.type = .pdfCompareGuide guard let win = self.view.window else { return } guideWC.finishHandle = { [weak self] winC, type in if type == .windowNewFinish { DispatchQueue.main.async { self?.loadOpenFileFunctionGuide(.measureGuide) } return } } guideWC.window?.collectionBehavior = [.canJoinAllSpaces] var rect = self.view.window!.frame rect.size.height -= 20 guideWC.window?.setFrame(rect, display: false) guideWC.window?.minSize = rect.size guideWC.window?.maxSize = rect.size self.view.window?.addChildWindow(guideWC.window!, ordered: .above) guideWC.show() } } else if showType == .measureGuide && KMGuideInfoWindowController.availableShow(.measureGuide) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.2) { self.guideInfoWindowController = KMGuideInfoWindowController.currentWC() guard let guideWC = self.guideInfoWindowController else { return } guard let _ = self.view.window else { return } guideWC.type = .measureGuide guideWC.window?.collectionBehavior = [.canJoinAllSpaces] var rect = self.view.window?.frame ?? .zero rect.size.height -= 20 guideWC.window?.setFrame(rect, display: false) guideWC.window?.minSize = rect.size guideWC.window?.maxSize = rect.size self.view.window?.addChildWindow(guideWC.window!, ordered: .above) guideWC.show() } } else if showType == .convertGuide && KMGuideInfoWindowController.availableShow(.convertGuide) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) { self.guideInfoWindowController = KMGuideInfoWindowController.currentWC() guard let guideWC = self.guideInfoWindowController else { return } guideWC.type = .convertGuide guard let win = self.view.window else { return } guideWC.purchaseHandle = { [weak self] windowVC in #if VERSION_DMG if IAPProductsManager.default().isAvailableAllFunction() { if IAPProductsManager.default().isAvailableAdvancedPDFToOffice() { //Convert: } else { let limitWC = KMPurchaseLimitWindowController.currentLimitWC() limitWC.continueBlock = { windowController in } limitWC.window?.center() limitWC.showWindow(nil) } } else { KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) } #else if IAPProductsManager.default().isAvailableAllFunction() { if IAPProductsManager.default().isAvailableAdvancedPDFToOffice() { //Convert: } else { var vc = KMToolCompareWindowController(toolType: .Convert, selectNum: 1) vc.showWindow(nil) } } else { KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) } #endif } guideWC.window?.collectionBehavior = [.canJoinAllSpaces] var rect = self.view.window?.frame ?? .zero rect.size.height -= 20 guideWC.window?.setFrame(rect, display: false) guideWC.window?.minSize = rect.size guideWC.window?.maxSize = rect.size self.view.window?.addChildWindow(guideWC.window!, ordered: .above) guideWC.show() } } else { } } func checkFirstTrialController() -> Void { #if VERSION_DMG //打开文档后引导相关 if VerificationManager.default().status == .none { let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "" let lastVersion = UserDefaults.standard.object(forKey: "SKLastTrialVersionMainDocumentLaunchedKey") as? String ?? "" if lastVersion.isEmpty || lastVersion != appVersion { UserDefaults.standard.setValue(appVersion, forKey: "SKLastTrialVersionMainDocumentLaunchedKey") UserDefaults.standard.synchronize() KMPurchaseCompareWindowController.sharedInstance().showWindow(nil) } } #endif } // MARK: - Private Methods func isPDFPageCountExceedsLimit(filePath: String) -> Bool { let url = URL(fileURLWithPath: filePath) guard let document = PDFDocument(url: url) else { return false } let pageCount = document.pageCount return pageCount > 30 } // MARK: - Redact 【标记密文】 func redactApplyAction() { let returnCode = KMAlertTool.runModelForMainThread_r(message: "", informative: KMLocalizedString("This will permanently remove the redacted information from this document. Once you save this document, you won’t be able to retrieve the redacted information."), buttons: [KMLocalizedString("Apply"), KMLocalizedString("Cancel")]) if returnCode == .alertFirstButtonReturn { DispatchQueue.main.async { self.saveAsPath() } } } func redactMultipageAction(redactAnnotation:CPDFRedactAnnotation) { let pagesWindowController = KMRedactSelectPagesWindowController(document: listView.document) self.km_beginSheet(windowC: pagesWindowController) pagesWindowController.callback = { [weak self] pages in if pages.count > 0 { self?.listView.redactAddAnnotationPages(pages, redactAnnotation: redactAnnotation) } } } func setPropertiesDefault(annotation:CPDFRedactAnnotation) { CPDFRedactAnnotation.update_defaultOutlineColor(annotation.borderColor()) CPDFRedactAnnotation.update_defaultFillColor(annotation.interiorColor()) CPDFRedactAnnotation.update_defaultTextColor(annotation.fontColor()) CPDFRedactAnnotation.update_defaultFontSize(annotation.fontSize) CPDFRedactAnnotation.update_defaultFontAlignment(annotation.alignment()) CPDFRedactAnnotation.update_defaultOverlayText(annotation.overlayText()) } func exeRedactConfirm(_ type: KMRedactConfirmType, callback: @escaping () -> ()?) { let windowController = KMRedactConfirmWindowController(type) self.currentWindowController = windowController self.view.window?.beginSheet(windowController.window!) windowController.itemClick = { [weak self] index in if (index == 2) { /// 取消 self?.view.window?.endSheet((self?.currentWindowController.window)!) self?.currentWindowController = nil callback() return } self?.view.window?.endSheet((self?.currentWindowController.window)!) self?.currentWindowController = nil let panel = NSSavePanel() panel.nameFieldStringValue = "[新文件]"+((self?.listView.document?.documentURL.lastPathComponent) ?? "") let button = NSButton.init(checkboxWithTitle: "保存后打开文档", target: nil, action: nil) button.state = .on panel.accessoryView = button panel.isExtensionHidden = true panel.beginSheetModal(for: (self?.view.window!)!) { response in if response != .OK { callback() return } if (type == .redactOne) { let anno = self!.listView.activeAnnotation if (anno == nil || (anno?.isKind(of: CPDFRedactAnnotation.self)) == false) { callback() return } (anno as! CPDFRedactAnnotation).applyRedaction() } else if (type == .redactAll) { self?.listView.document?.applyRedactions() } else if (type == .eraserOne) { let anno = self!.listView.activeAnnotation if (anno == nil || (anno?.isKind(of: CPDFRedactAnnotation.self)) == false) { callback() return } anno?.page.erasureRedact(from: anno!.bounds) } else if (type == .eraserAll) { KMRedactTools.eraserDocument((self?.listView.document)!) { result, errorAnno in if (result == false) { callback() return } } } self!.listView.document?.write(to: panel.url) if (button.state == .on) { NSDocumentController.shared.openDocument(withContentsOf: panel.url!, display: true) { document, alreadyOpen, error in } } else { NSWorkspace.shared.activateFileViewerSelecting([panel.url!]) } callback() } } } // MARK: - 保存文档 internal func needSaveDocument() -> Bool { if (self.isPDFDocumentEdited) { return self.isPDFDocumentEdited } if (self.needSave) { return self.needSave } let document: KMMainDocument? = self.myDocument as? KMMainDocument if (document?.isDocumentEdited == nil || document?.isDocumentEdited == false) { return false } return true } internal func saveDocument(overlookDocumentIfEdited overlook: Bool = false) { let document: KMMainDocument? = self.myDocument as? KMMainDocument if (overlook) { document?.save(nil) return } if (self.isPDFDocumentEdited) { self.clearIsPDFDocumentEdited() self.needSave = false document?.save(nil) return } if (document?.isDocumentEdited == nil || document?.isDocumentEdited == false) { return } document?.save(nil) } internal func asyncSaveDocument(overlookDocumentIfEdited overlook: Bool = false, callback:@escaping KMCommonBlock) { let document: KMMainDocument? = self.myDocument as? KMMainDocument if (overlook) { DispatchQueue.main.async { document?.save(nil) callback() } return } if (self.isPDFDocumentEdited) { self.clearIsPDFDocumentEdited() self.needSave = false DispatchQueue.main.async { document?.save(nil) callback() } return } if (document?.isDocumentEdited == nil || document?.isDocumentEdited == false) { callback() return } DispatchQueue.main.async { document?.save(nil) callback() } } internal func saveDocumentWithProgressAlert(callback:@escaping KMCommonBlock) { // 显示进度 AutoSaveManager.manager.isSaving = true self.showProgressWindow(message: NSLocalizedString("Save", comment: "") + "PDF") self.progressC?.maxValue = 3.0 self.progressC?.increment(by: 1.0) // 保存文档 self.asyncSaveDocument { [weak self] params in // 执行进度 [假进度] self?.progressC?.increment(by: 1.0) self?.progressC?.increment(by: 1.0) DispatchQueue.main.asyncAfter(deadline: .now()+0.1) { // 隐藏进度 self?.hiddenProgressWindow() DispatchQueue.main.asyncAfter(deadline: .now()+1) { AutoSaveManager.manager.isSaving = false } // 回调 callback() } } } func SaveTempPDFDocumentToURLPath(tempPath: String) { self.document?.write(toFile: tempPath) } // MARK: - 定时保存 func addAutoSaveEvent() { if (self.autoSaveTimer != nil) { self.autoSaveTimer?.invalidate() self.autoSaveTimer = nil } if self.document != nil { self.autoSaveTimer = Timer.scheduledTimer(withTimeInterval: AutoSaveManager.manager.timeInterval * 60, repeats: true, block: { [weak self] timer in self?.autoSaveTimerAction(timer) }) } self.checkAutoSaveInfo() } func checkAutoSaveInfo() { guard let cnt = AutoSaveManager.manager.autoSavePaths?.count, cnt > 0 else { return } if AutoSaveManager.manager.autoSaveAlertShow { return } AutoSaveManager.manager.autoSaveDidEndAction = false AutoSaveManager.manager.autoSaveAlertShow = true let blockSaveWindow = AutoSavePopController() blockSaveWindow.cancelHandle = { [weak self] windowController in AutoSaveManager.manager.autoSaveDidEndAction = true AutoSaveManager.manager.clearCache() self?.km_quick_endSheet() } blockSaveWindow.confirmHandle = { [weak self] windowController in self?.km_quick_endSheet() self?.saveAutoSaveInfo() } self.km_beginSheet(windowC: blockSaveWindow) } func saveAutoSaveInfo() { let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.allowsMultipleSelection = false let win = NSApp.keyWindow != nil ? NSApp.keyWindow : self.view.window openPanel.beginSheetModal(for: win!) { result in if (result == .OK) { let folderPath = openPanel.url?.path ?? openPanel.url?.absoluteString for path in AutoSaveManager.manager.opendPaths ?? [] { let _path = path as? String var newPath = "\(folderPath ?? "")/\(_path?.lastPathComponent ?? "")" newPath = self.getValidFilePath(newPath) do { try FileManager.default.moveItem(atPath: _path ?? "", toPath: newPath) } catch { NSWorkspace.shared.activateFileViewerSelecting([URL(fileURLWithPath: newPath)]) } } AutoSaveManager.manager.clearCache() } AutoSaveManager.manager.autoSaveDidEndAction = true } } func autoSaveTimerAction(_ timer: Timer) { if (self.document == nil || self.listView.document?.documentURL.path == nil) { return } if AutoSaveManager.manager.autoSaveDidEndAction == false { //防止提示弹窗出现后,未进行任何操作又进入自动保存的机制 return } if let data = self.document?.isLocked, data { return } if AutoSaveManager.manager.autoSaveEnabled == false { return } let documentArray = NSDocumentController.shared.documents var didFileEdit = false for doc in documentArray { if doc.fileURL?.path == self.document?.documentURL.path { didFileEdit = doc.isDocumentEdited break } } if (didFileEdit == false) { return } AutoSaveManager.manager.isSaving = true let savePath = AutoSaveManager.manager.autoSaveWithPath(self.listView.document?.documentURL.path ?? "") if (!self.document!.isLocked) { self.document?.write(to: URL(fileURLWithPath: savePath)) } DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { AutoSaveManager.manager.isSaving = false } } func removeAutoSaveInfo() { if self.autoSaveTimer != nil { self.autoSaveTimer?.invalidate() self.autoSaveTimer = nil } if AutoSaveManager.manager.autoSaveDidEndAction == false { //防止提示弹窗出现后,未进行任何操作又进入自动保存的机制 return } if AutoSaveManager.manager.autoSaveEnabled == false { return } if self.document == nil || self.listView.document?.documentURL.path == nil { return } AutoSaveManager.manager.removeAutoSavePath(self.listView.document?.documentURL.path ?? "") } // MARK: - 选择缩放模式 @objc public func selectZoom(_ type: KMPDFZoomType) { switch type { case .width: self.listView.autoScales = true break case .fit: if let pageHeight = self.listView.currentPage()?.size.height, pageHeight > 0 { let pdfviewHeight = self.listView.bounds.size.height self.listView.scaleFactor = pdfviewHeight/pageHeight self.listView.autoScales = false } break case .actualSize: if self.listView.scaleFactor != 1.0 { self.listView.scaleFactor = 1.0 self.listView.autoScales = false } break case .zoom_In: self.doZoomIn(nil) break case .zoom_Out: self.doZoomOut(nil) break } } func doZoomIn(_ sender: Any?) { if (self.listView.canZoomIn) { self.listView.zoomIn(nil) } } func doZoomOut(_ sender: Any?) { if (self.listView.canZoomOut) { self.listView.zoomOut(nil) } } // MARK: - Event 监听 private func addEventMonitor() { if (self.eventMonitor != nil) { self.removeEventMonitor() } self.eventMonitor = NSEvent.addLocalMonitorForEvents(matching: [.scrollWheel, .leftMouseDown, .leftMouseUp]) { [weak self] event in if (event.type == .scrollWheel && event.modifierFlags.contains(.option)) { // Alt + 鼠标滚轮 self?.listView.magnifyWheel(event) return nil } else if event.type == .leftMouseDown { let point = event.locationInView(self?.listView ?? NSView()) let presentationDrawView = self?.listView.presentationDrawView if let data = self?.interactionMode, data == .presentation,CGRectContainsPoint(self?.listView.frame ?? .zero, point),presentationDrawView?.isHidden == true { // 幻灯片模式下 if point.x >= (self?.listView.frame.maxX ?? 0) / 2 { let can = self?.listView.canGoToNextPage() ?? false if can { self?.listView.goToNextPage(nil) } } else { let can = self?.listView.canGoToPreviousPage() ?? false if can { self?.listView.goToPreviousPage(nil) } } return nil } } return event } } private func removeEventMonitor() { if (self.eventMonitor != nil) { KMPrint("已移除事件监听") NSEvent.removeMonitor(self.eventMonitor as Any) self.eventMonitor = nil } } // MARK: - Tools func pdfViewCanHorizontalScroll() -> Bool { let scroll = self.listView.scroll() if (scroll == nil) { return false } return scroll?.horizontalScroller?.isHidden == nil ? false : !(scroll!.horizontalScroller!.isHidden) } func pdfViewCanVerticalScroll() -> Bool { let scroll = self.listView.scroll() if (scroll == nil) { return false } return scroll?.verticalScroller?.isHidden == nil ? false : !(scroll!.verticalScroller!.isHidden) } // MARK: - Public Methods // 清理数据 [eg. 通知] public func clearData() { KMThumbnailCache.shared.clearCache() self.removeNotifications() if (self.listView.spellingTag() > 0) { NSSpellChecker.shared.closeSpellDocument(withTag: self.listView.spellingTag()) } self.removeAutoSaveInfo() self.myDocument = nil if textFieldSheet.window?.isVisible == true { textFieldSheet.close() } if NSColorPanel.shared.isVisible == true { NSColorPanel.shared.close() } } public func clearSecureOptions() { self._secureOptions = nil self.documentAttribute = nil } public func clearRemoveSecureFlag() { self._removeSecureFlag = false } public func recordIsPDFDocumentEdited(type: KMSubscribeWaterMarkType = .none) { km_synchronized(self) { self.model.isPDFDocumentEdited = true if type == .editText || type == .editImage { } if let _document = self.myDocument { KMTools.setDocumentEditedState(document: _document) } } } public func clearIsPDFDocumentEdited() { km_synchronized(self) { self.model.isPDFDocumentEdited = false } } func showSnapshots(setups: NSArray?) { if self.listView.document != nil { for setup in setups ?? [] { let swc = KMSnapshotWindowController() swc.delegate = self swc.setPdfDocument(self.listView.document, setup: setup as? NSDictionary) swc.setForceOnTop(self.interactionMode != .normal) self.myDocument?.addWindowController(swc) } } } // MARK: - Noti Actions internal func documentDidUnlockNotification(_ sender: Notification) { if (self.listView.document != nil && self.listView.document.isEqual(to: sender.object)) { if (self.myDocument == nil) { return } if (self.listView.document.allowsPrinting && self.listView.document.allowsCopying) { self.hiddenSecureLimitTip() } let isUnlockFromKeychain = (self.myDocument as? KMMainDocument)?.isUnlockFromKeychain ?? false if (isUnlockFromKeychain || self.model.isSaveKeyChain == false) { return } let type = SettingsManager.sharedInstance.keychainType if (type == .never) { return } if (type == .always) { self.myDocument?.savePasswordInKeychain(self.listView.document.password, self.listView.document) return } // 保存到钥匙串 let alert = NSAlert() alert.messageText = NSLocalizedString("Remember Password?", comment: "") alert.informativeText = NSLocalizedString("Do you want to save this password in your Keychain?", comment: "") alert.addButton(withTitle: NSLocalizedString("Yes", comment: "")) alert.addButton(withTitle: NSLocalizedString("No", comment: "")) if (alert.runModal() == .alertFirstButtonReturn) { // 保存密码 self.myDocument?.savePasswordInKeychain(self.listView.document.password, self.listView.document) return } } } internal func applicationWillTerminateNotification(_ sender: Notification) { self.savePageNumberIfNeed() self.saveDocument() } }