// // KMMainViewController.swift // PDF Reader Pro // // Created by wanjun on 2022/12/15. // import Cocoa import KMComponentLibrary @objcMembers class KMMainViewController: KMBaseViewController, NSTextFieldDelegate { @IBOutlet var contendBox: NSBox! @IBOutlet var toolbarBox: NSBox! //工具栏Box @IBOutlet var bottomContendBox: NSBox! // @IBOutlet var sidebarBox: NSBox! //左侧边栏Box @IBOutlet var infoContendSplitView: KMPDFSplitView! @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 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 pdfBottomToolbar: KMSplitToolbar? //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? //MARK: - 旧代码,有需要用到的拿出来,写好备注 @IBOutlet weak var leftView: NSView! var model = KMMainModel() //自动滚动 var autoFlowOptionsSheetController: KMAutoFlowOptionsSheetController? //Search var searchIndex: Int = 0 //Form var formAlertView: KMFormAlertView? //Secure var secureAlertView: KMSecureAlertView? //对比 var isCompareModel: Bool = false { didSet { } } //合并 var mergeWindowController: KMMergeWindowController? //密码弹窗 var passwordWindow: KMPasswordInputWindow? //对比 var compressWIndowControllerNew: KMCompressWIndowControllerNew? // var securityWindowController: KMSecurityWindowController? //引导 var guideInfoWindowController: KMGuideInfoWindowController? //春季活动 var recommondPopWindowVC: KMRecommondPopWindow? 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 leftSideViewController: KMLeftSideViewController = KMLeftSideViewController.init(type: KMLeftMethodMode()) var searchResults: [KMSearchMode] = [] var mwcFlags: MwcFlags = MwcFlags() weak var browserWindowController: KMBrowserWindowController? //慎直接使用这个方法 var cropSettingWindowController: KMCropSettingWindowController! var currentWindowController: NSWindowController! var savedNormalSetup: NSMutableDictionary = NSMutableDictionary() //数字签名 var digitalSignController: KMPDFDigitalSignViewController? var redactController: KMPDFRedactViewController! let CPDFOfficeLeftSidePaneWidthKey = "CPDFOfficeLeftSidePaneWidthKey" let CPDFOfficeRightSidePaneWidthKey = "CPDFOfficeRightSidePaneWidthKey" var extract: KMExtractImageWindowController? var functionWidth: Double { get { if self.viewManager.isPDFReadMode { if !self.model.isShowBOTA { return 0 } } return 48-4 } } var pageNumber: UInt? var pdfEditController: KMPDFEditViewController? { get { return self.getPDFEditController() } } var autoSaveTimer: Timer? private var _documentFirstLoad: Bool = true var eventMonitor: Any? var keyEventMonitor: 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 } } } var distanceMeasureInfoWindowController: CDistanceMeasureInfoWindowController? var perimeterMeasureInfoWindowController: CPerimeterMeasureInfoWindowController? var areaMeasureInfoWindowController: CAreaMeasureInfoWindowController? var srHanddler: KMSearchReplaceHanddler = KMSearchReplaceHanddler() //MARK: - func deinit { NotificationCenter.default.removeObserver(self) self.listView.delegate = nil self.listView.document?.delegate = nil self.removeEventMonitor() self.removeKeyEventMonitor() } override func viewDidLoad() { super.viewDidLoad() // Do view setup here. toolbarManager.pdfViewManager = viewManager } override func viewDidAppear() { super.viewDidAppear() setupUI() } func setupUI() { initPDFView() initToolbar() initSideBar() setUpSplitView() } private func documentLoadComplete() { initBotaView() } func leftSidePaneIsOpen() -> Bool { if(botaViewController != nil) { return infoContendSplitView.isSubviewCollapsed(botaViewController!.view) } return false } private func toggleOpenLeftSide(pdfSideBarType: KMPDFSidebarType) { if(leftSidePaneIsOpen() == false) { infoContendSplitView.setPosition(264, ofDividerAt: 0) } if pdfSideBarType == .search { KMPrint(" search") } else if pdfSideBarType == .thumbnail { botaViewController?.leftsideType = pdfSideBarType KMPrint(" thumbnail") } 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 { KMPrint(" annotation") } } private func toggleCloseLeftSide() { if(leftSidePaneIsOpen() == true) { infoContendSplitView.setPosition(-20, ofDividerAt: 0) } } //MARK: - PDFView func initPDFView() { listView.autoresizingMask = [.width, .height] listView.delegate = self listView.pdfListViewDelegate = self listView.document = self.document reloadPDFSplitInfo() } func updatePDFViewAnnotationMode() { let toolbarMode = viewManager.toolMode let subToolMode = viewManager.subToolMode if toolbarMode == .None { listView.annotationType = .unkown listView.toolMode = .noteToolMode } else if toolbarMode == .Markup { listView.toolMode = .noteToolMode } else if toolbarMode == .Edit { if subToolMode == .None { if listView.toolMode != .editPDFToolMode { listView.toolMode = .editPDFToolMode listView.configPDFEditingInfo() } listView.annotationType = .editTextImage listView.setShouAddEdit([]) listView.change([.text, .image]) removeCropController() } else if subToolMode == .Edit_text { if listView.toolMode != .editPDFToolMode { listView.toolMode = .editPDFToolMode listView.configPDFEditingInfo() } listView.annotationType = .addText listView.setShouAddEdit([.text]) listView.change(.text) } else if subToolMode == .Edit_Image { if listView.toolMode != .editPDFToolMode { listView.toolMode = .editPDFToolMode listView.configPDFEditingInfo() } listView.annotationType = .addImage listView.setShouAddEdit([.image]) listView.change(.image) } else if subToolMode == .Edit_Link { listView.toolMode = .noteToolMode listView.annotationType = .link } else if subToolMode == .Edit_Crop { // listView.toolMode = .selectToolMode showCropController() } } else if toolbarMode == .Form { } else if toolbarMode == .Fill { } } //MARK: - SplitView func setUpSplitView() { infoContendSplitView.wantsLayer = true infoContendSplitView.layer?.backgroundColor = NSColor.clear.cgColor infoContendSplitView.delegate = self infoContendSplitView.layer?.masksToBounds = true infoContendSplitView.setPosition(-10, ofDividerAt: 0) infoContendSplitView.setPosition(CGRectGetWidth(infoContendSplitView.frame), ofDividerAt: 1) } 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?.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() refreshToolbarView() } func refreshToolbarView() { let _manager = viewManager if _manager.isPageEditMode { toolbarBoxHeightConst.constant = 80 } else if _manager.editType == .watermark || _manager.editType == .background || _manager.editType == .header_Footer || _manager.editType == .bates { toolbarBoxHeightConst.constant = 40 } else if _manager.toolMode == .Markup || _manager.toolMode == .Edit || _manager.toolMode == .Form || _manager.toolMode == .Fill || _manager.toolMode == .Convert || _manager.toolMode == .Protect || _manager.toolMode == .Tools { toolbarBoxHeightConst.constant = 80 } else { toolbarBoxHeightConst.constant = 40 } } func toolbarViewModeChanged() { updatePDFViewAnnotationMode() if viewManager.showRightSide == true { openRightPane() } else { closeRightPane() } } //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() } //MARK: - 侧边栏 func initBotaView() { 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) } } //MARK: - 右侧属性栏 func initRightSideController() { if rightSideController == nil { rightSideController = KMRightSideController.init() } rightSideController?.view.frame = CGRectMake(0, 0, 264, 680) rightSideController?.view.autoresizingMask = [.height, .maxXMargin] } func removeRightSideController() { rightSideController?.view.removeFromSuperview() rightSideController = nil } @objc func openRightPane() -> Void { initRightSideController() rightSideController?.view.frame = CGRectMake(CGRectGetWidth(bottomContendBox.frame)-264, 0, 264, CGRectGetHeight(bottomContendBox.frame)) bottomContendBox.addSubview(rightSideController!.view) infoSplitViewRightConst.constant = 264 rightSideController?.viewManager = self.viewManager } @objc func closeRightPane() -> Void { removeRightSideController() infoSplitViewRightConst.constant = 0 } //MARK: - PDFDisplayView func updatePDFDisplaySettingView() { if viewManager.showDisplayView { infoSplitViewLeftConst.constant = 264 } else { infoSplitViewLeftConst.constant = 44 } if viewManager.showDisplayView { if displaySettingController == nil { displaySettingController = KMNDisplayViewController.init() } displaySettingController?.view.frame = CGRectMake(0, 0, 264, CGRectGetHeight(bottomContendBox.frame)) displaySettingController?.view.autoresizingMask = [.height, .maxXMargin] bottomContendBox.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() } } func exitPageEditMode() { if pageEditViewController != nil { pageEditViewController?.view.removeFromSuperview() pageEditViewController = nil } } //MARK: - 阅读模式 func openPDFReadMode() { if viewManager.showDisplayView { viewManager.showDisplayView = false pdfToolbarController?.reloadLeftIconView() updatePDFDisplaySettingView() } infoSplitViewLeftConst.constant = 0 toolbarBoxHeightConst.constant = 0 view.window?.makeFirstResponder(listView) var 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) } func exitPDFReadMode() { viewManager.isPDFReadMode = false updatePDFDisplaySettingView() refreshToolbarView() } //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 } } 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) setUpPDFBottomToolbar() setupSplitPDFController() if listView.viewSplitMode == .horizontal { pdfSplitView.isVertical = false } else if listView.viewSplitMode == .vertical { pdfSplitView.isVertical = true } } } func setUpPDFBottomToolbar() { if pdfBottomToolbar != nil { pdfBottomToolbar = nil } pdfBottomToolbar = KMSplitToolbar.init() pdfBottomToolbar?.frame = CGRectMake(CGRectGetWidth(pdfSplitTopView.frame)/2-144, 20, 288, 40) pdfBottomToolbar?.pdfView = self.listView pdfBottomToolbar?.reloadData() pdfSplitTopView.addSubview(pdfBottomToolbar!) } func reloadPDFBottomToolbar() { if viewManager.splitShowBottomBar { pdfBottomToolbar?.isHidden = false pdfBottomToolbar?.reloadData() } else { pdfBottomToolbar?.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 } func exitEditToolbarView() { listView.isHidden = false viewManager.editType = .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 refreshToolbarView() toolbarBox.contentView = pdfToolbarController?.view } //MARK: - Crop裁剪 func showCropController() { listView.isHidden = true if cropController == nil { cropController = KMCropController.init() } cropController?.view.frame = CGRectMake(44, 0, CGRectGetWidth(bottomContendBox.frame)-44, CGRectGetHeight(bottomContendBox.frame)) cropController?.view.autoresizingMask = [.maxXMargin, .width, .height] // cropController?.delegate = self bottomContendBox.addSubview(cropController!.view) updateCropDocument() } func updateCropDocument() { guard let controller = cropController else { return } controller.pdfDocument = nil let editDocument = CPDFDocument.init() let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) controller.pdfDocument = editDocument controller.reloadData() } func removeCropController() { listView.isHidden = false if cropController != nil { cropController?.view.removeFromSuperview() cropController = nil } } //MARK: - Watermark水印 func showWatermarkController() { listView.isHidden = true 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.addSubview(watermarkViewController!.view) watermarkViewController?.editSubType = editToolbarView?.editSubType ?? .template updateWatermarkDocument() } func updateWatermarkDocument() { guard let controller = watermarkViewController else { return } controller.pdfDocument = nil let editDocument = CPDFDocument.init() let page = listView.document.page(at: UInt(listView.currentPageIndex)) editDocument?.insertPageObject(page, at: 0) watermarkViewController?.pdfDocument = editDocument 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() } } func batchAddWatermark() { } func batchRemoveWatermark() { } //MARK: - Background背景 func showBackgroundController() { listView.isHidden = true 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.addSubview(backgroundViewController!.view) backgroundViewController?.editSubType = editToolbarView?.editSubType ?? .template 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 background = listView.document.background() background?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() } func batchAddBackground() { } func batchRemoveBackground() { } //MARK: - header&footer func showHeaderFooterController() { listView.isHidden = true 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.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?.pdfDocument = editDocument headerFooterViewController?.reloadData() } func removeHeaderFooter() { let headerFooter = listView.document.headerFooter() headerFooter?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() } func batchAddHeaderFooter() { } func batchRemoveHeaderFooter() { } //MARK: - Bates func showBatesController() { listView.isHidden = true 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.addSubview(batesViewController!.view) batesViewController?.editSubType = editToolbarView?.editSubType ?? .template updateBatesDocument() } 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 bates = listView.document.bates() bates?.clear() listView.document?.refreshPageData() listView.layoutDocumentView() } func batchAddBates() { } func batchRemoveBates() { } } //MARK: - NSSplitViewDelegate extension KMMainViewController: NSSplitViewDelegate { func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool { return true } func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool { return true } func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { return proposedMaximumPosition } func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { return proposedMinimumPosition } func splitView(_ splitView: NSSplitView, constrainSplitPosition proposedPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { if dividerIndex == 0 { if proposedPosition > CGRectGetWidth(infoContendSplitView.frame)/2 - 10 { print(CGRectGetWidth(infoContendSplitView.frame)/2 - 10, NSDate()) return CGRectGetWidth(infoContendSplitView.frame)/2 - 10 } } else if dividerIndex == 1 { print(CGRectGetWidth(infoContendSplitView.frame)/2 - 10, NSDate()) } return proposedPosition } func splitViewDidResizeSubviews(_ notification: Notification) { let splitView = notification.object as? NSSplitView if((splitView?.isEqual(to: infoContendSplitView)) == true) { leftSplitViewResizeFinish() } 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 { func kmPDFToolbarControllerDidToolbarItemClicked(_ controller: KMPDFToolbarController, _ itemIdentifier: String) { print("toolbar点击", itemIdentifier) if itemIdentifier == KMPDFToolbar_ViewDisplay_Identifier { //Display updatePDFDisplaySettingView() } else if itemIdentifier == KMPDFToolbar_PageEdit_Identifier { if viewManager.isPageEditMode == true { enterPageEditMode() } else { exitPageEditMode() } } else if itemIdentifier == KMPDFToolbar_Markup_Identifier { } else if itemIdentifier == KMPDFToolbar_Edit_Identifier { } else if itemIdentifier == KMPDFToolbar_edit_link_Identifier { //Link } else if itemIdentifier == KMPDFToolbar_Form_Identifier { } else if itemIdentifier == KMPDFToolbar_Fill_Identifier { } else if itemIdentifier == KMPDFToolbar_Convert_Identifier { } else if itemIdentifier == KMPDFToolbar_Protect_Identifier { } else if itemIdentifier == KMPDFToolbar_Tools_Identifier { } else if itemIdentifier == KMPDFToolbar_convert_word_Identifier { let winC = KMConvertWordWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if itemIdentifier == KMPDFToolbar_convert_ppt_Identifier { 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 itemIdentifier == KMPDFToolbar_convert_RTF_Identifier { 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 itemIdentifier == KMPDFToolbar_convert_Text_Identifier { 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 itemIdentifier == KMPDFToolbar_convert_CSV_Identifier { 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 itemIdentifier == KMPDFToolbar_convert_excel_Identifier { let winC = KMConvertExcelWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if itemIdentifier == KMPDFToolbar_convert_HTML_Identifier { let winC = KMConvertHtmlWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: self.view.window, completionHandler: nil) } else if itemIdentifier == KMPDFToolbar_convert_Json_Identifier { let winC = KMConvertJsonWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: view.window, completionHandler: nil) } else if itemIdentifier == KMPDFToolbar_convert_image_Identifier { let winC = KMConvertImageWindowController() let model = KMDocumentModel(url: listView.document.documentURL) winC.documentModel = model winC.own_beginSheetModal(for: view.window, completionHandler: nil) } else if itemIdentifier == KMPDFToolbar_convert_imageToPDF_Identifier { NSApplication.ShowImageToPDFWindow() } else 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 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_undo_Identifier) { listView.undoManager?.undo() } else if(itemIdentifier == KMPDFToolbar_redo_Identifier) { listView.undoManager?.redo() } else { print("click else") } refreshToolbarView() toolbarViewModeChanged() } 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: - 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() reloadPDFBottomToolbar() } } //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() self.forceSubwindowsOnTop(false) } } 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?.reloadData() } else if view.editType == .background { backgroundViewController?.editSubType = editToolbarView?.editSubType ?? .template backgroundViewController?.reloadData() } else if view.editType == .header_Footer { headerFooterViewController?.editSubType = editToolbarView?.editSubType ?? .template headerFooterViewController?.reloadData() } else if view.editType == .bates { batesViewController?.editSubType = editToolbarView?.editSubType ?? .template batesViewController?.reloadData() } } func kmEditToolbarViewDidChooseBatch(_ view: KMEditToolbarView) { } func kmEditToolbarViewDidChooseApply(_ view: KMEditToolbarView) { let pageIndex = view.getSelectedPageIndex(listView.document) 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 } let pageString = view.getSelectedPageString(listView.document, pageIndex) 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 { exitEditToolbarView() } else if view.editType == .bates { exitEditToolbarView() } } func kmEditToolbarViewDidChooseExit(_ view: KMEditToolbarView) { if view.editType == .watermark { if view.applyEnable { let alert = NSAlert() alert.messageText = NSLocalizedString("There are unapplied watermark 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() } } else if view.editType == .background { exitEditToolbarView() } else if view.editType == .header_Footer { exitEditToolbarView() } else if view.editType == .bates { exitEditToolbarView() } } } //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 kmBackgroundControllerDidWatermarkUpdated(_ 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 kmHeaderFooterControllerDidUpdateMode(_ 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() var indexpaths: Set = [] indexpaths.insert(IndexPath(item: listView.currentPageIndex, section: 0)) botaViewController?.thumnailViewController?.selectionIndexPaths = indexpaths //分屏视图 reloadPDFBottomToolbar() 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) } } //水印 updateWatermarkDocument() // } func pdfViewScaleDidChanged(_ pdfView: CPDFView!) { pdfToolbarController?.reloadSelectZoomView() reloadPDFBottomToolbar() //分屏视图 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 == kKMPurchaseProductURLString { //跳转订阅比较表 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!) { // 文本区块 选中文本已经变化 } func pdfViewEditingAreaDidChanged(_ pdfView: CPDFView!) { //编辑模块变化 rightSideController?.reloadDataWithPDFView(pdfView: (pdfView as! CPDFListView)) if pdfView is CPDFListView { (pdfView as! CPDFListView).isEditImage = false } } func pdfViewEditingCropBoundsDidChanged(_ pdfView: CPDFView!, editing editArea: CPDFEditArea!) { if editArea != nil && (editArea is CPDFEditImageArea){ self.listView.cropAreas = editArea as? CPDFEditImageArea } } //编辑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 cfont = CPDFFont(familyName: model.fontName, fontStyle: model.fontStyle) let fontNameZ = CPDFFont.convertAppleFont(cfont) let font = NSFont(name: fontNameZ ?? "Helvetica", size: fontSize) let attri = CEditAttributes() attri.font = font! 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() } func pdfViewMobileEditingMove(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { rightSideController?.reloadEditingAreas() } func pdfViewMobileEditingEnd(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { rightSideController?.reloadEditingAreas() } func pdfViewEditingSelectCharDidChanged(_ pdfView: CPDFView!) { rightSideController?.reloadEditingAreas() } func pdfViewEditingExitCropMode(_ pdfView: CPDFView!, forEditing editingArea: CPDFEditImageArea!) { rightSideController?.reloadEditingAreas() } 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!) { } 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.annotationType == .addImage || self.listView.annotationType == .addText { 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 } if (KMSystemMenu.isEditSelector(sel: action)) { if (KMSystemMenu.Edit.deleteSelector == action) { isTakesEffect.pointee = true return self.listView.activeAnnotations.count > 0 } else if (KMSystemMenu.Edit.copySelector == action) { isTakesEffect.pointee = true return true//self.listView.canCopy() } else if (KMSystemMenu.Edit.cutSelector == action) { isTakesEffect.pointee = true return self.listView.canCopy() } else if (KMSystemMenu.Edit.pasteSelector == action) { isTakesEffect.pointee = true return self.listView.canPaste() } } isTakesEffect.pointee = false return false } //MARK: - CPDFListViewDelegate func cPDFListView(_ pdfListView: CPDFListView, didDelete annotation: CPDFAnnotation, in pdfPage: CPDFPage) { self.leftSideViewController.updateThumbnail(at: Int(pdfPage.pageIndex())) } func pdfListViewChangeatioActiveAnnotations(_ pdfListView: CPDFListView!, forActiveAnnotations annotations: [CPDFAnnotation]!, isRightMenu: Bool) { self.view.window?.makeFirstResponder(self.listView) if isRightMenu { } else if annotations.count > 0 { if annotations.count > 1 { let fristAnnotation = annotations.first var isSameAnnotation = true let className = NSStringFromClass(fristAnnotation!.classForCoder) for annotation in annotations { let cunrrentClassName = NSStringFromClass(annotation.classForCoder) if (className == "CPDFSquareAnnotation") || (className == "CPDFCircleAnnotation") || (className == "CPDFLineAnnotation") { if (cunrrentClassName != "CPDFSquareAnnotation") && (cunrrentClassName != "CPDFCircleAnnotation") && (cunrrentClassName != "CPDFLineAnnotation") { isSameAnnotation = false } } else { if className != cunrrentClassName { isSameAnnotation = false } } } if isSameAnnotation == false { } else { self.openRightPane() } self.rightSideController?.reloadDataWithPDFView(pdfView: pdfListView) } else { let fristAnnotation = annotations.first let className = NSStringFromClass(fristAnnotation!.classForCoder) if self.viewManager.isPDFReadMode { self.closeRightPane() } else { if className != "CPDFStampAnnotation" && className != "CPDFSignatureAnnotation" && className != "CPDFListStampAnnotation" { self.openRightPane() } self.rightSideController?.reloadDataWithPDFView(pdfView: pdfListView) } } if (listView.activeAnnotation.isKind(of: CPDFLineAnnotation.self)) { if (!(listView.activeAnnotation as! CPDFLineAnnotation).isMeasure) { cancelMeasureType() } else { if distanceMeasureInfoWindowController == nil { let measureInfo = CPDFDistanceMeasureInfo() distanceMeasureInfoWindowController = CDistanceMeasureInfoWindowController() distanceMeasureInfoWindowController?.measureInfo = measureInfo distanceMeasureInfoWindowController?.delegate = self } } } else if (!listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) && !listView.activeAnnotation.isKind(of: CPDFPolylineAnnotation.self)) { cancelMeasureType() } else if (listView.activeAnnotation.isKind(of: CPDFPolygonAnnotation.self) || listView.activeAnnotation.isKind(of: CPDFPolylineAnnotation.self)) { if perimeterMeasureInfoWindowController == nil { let measureInfo = CPDFPerimeterMeasureInfo() perimeterMeasureInfoWindowController = CPerimeterMeasureInfoWindowController() perimeterMeasureInfoWindowController?.measureInfo = measureInfo perimeterMeasureInfoWindowController?.delegate = self } if areaMeasureInfoWindowController == nil { let measureInfo = CPDFAreaMeasureInfo() areaMeasureInfoWindowController = CAreaMeasureInfoWindowController() areaMeasureInfoWindowController?.measureInfo = measureInfo areaMeasureInfoWindowController?.delegate = self } } } else if (annotations.count == 0){ if pdfListView.annotationType == .unkown { self.closeRightPane() } else { if self.viewManager.isPDFReadMode { self.closeRightPane() } else { self.openRightPane() } } } } func pdfListViewChangedAnnotationType(_ pdfListView: CPDFListView!, for annotationType: CAnnotationType) { if(annotationType == .unkown) { self.closeRightPane() } let aType = annotationType if aType.isMarkup() || aType == .anchored || aType == .freeText || aType.isSquare() || aType == .link { KMDataManager.ud_set(annotationType.rawValue, forKey: SKLastAnnotationModeKey) } } ///开始定位链接注释 func pdfListViewLinkDestinationStart(_ pdfListView: CPDFListView!, withActiveAnnotation annotation: CPDFAnnotation!) { } ///刷新链接注释 func pdfListViewLinkDestinationEnd(_ pdfListView: CPDFListView!, withActiveAnnotation annotation: CPDFAnnotation!) { } func pdfListViewMenuItemsEditing(at point: CGPoint, for page: CPDFPage!, menuItems: [NSMenuItem]!) -> [NSMenuItem]! { if (listView.toolMode != CToolMode.editPDFToolMode) { return menuItems } var tMenuItems = menuItems; if(listView.isSelectEditCharRange() || listView.isSelecteditArea(with: point)) { tMenuItems?.append(NSMenuItem.separator()) } let areas = self.listView.editingAreas() ?? [] if areas.count == 1 { let fristAreas = areas.first if fristAreas is CPDFEditImageArea { self.listView.selectImageAreas = fristAreas as? CPDFEditImageArea if self.listView.isEditImage { tMenuItems?.removeAll() tMenuItems?.append(self.corpImageMenuItem()) tMenuItems?.append(self.cancelCorpImageMenuItem()) tMenuItems?.append(self.restoreCorpImageMenuItem()) } else { tMenuItems?.append(NSMenuItem.separator()) tMenuItems?.append(self.cutImageArea()) tMenuItems?.append(self.replaceImageArea()) tMenuItems?.append(self.exportImageArea()) } } else { if tMenuItems?.count != 1 { tMenuItems?.swapAt(0, 1) } } } else if areas.count == 0 { tMenuItems?.append(NSMenuItem.separator()) tMenuItems?.append(self.addText()) tMenuItems?.append(self.addImage()) } return tMenuItems } func pdfListViewMenu(forEvent pdfListView: CPDFListView!, for theEvent: NSEvent!, click menu: AutoreleasingUnsafeMutablePointer!, isMoveSelectAnno: Bool) { self.mouseRightMenuEvent = theEvent var currentMenu : NSMenu = menu.pointee! if let activeAnno = listView.activeAnnotation as? KMTableAnnotation {//Table var pagePoint = NSPoint() _ = self.listView.pageAndPoint(&pagePoint, for: theEvent, nearest: true) currentMenu.removeAllItems() let annotation = activeAnno annotation.completeEditCellText() if !(NSIsEmptyRect(annotation.drawRect)) { annotation.drawLine(pagePoint) NotificationCenter.default.post(name: NSNotification.Name.KMPDFViewTableAnnotationDidChange, object: self, userInfo: ["point": NSValue(point: pagePoint)]) } if (annotation.rowNumber - annotation.currentCell.row - 1) < 0 { return } currentMenu = tableMenu(currentMenu, withTable: listView.activeAnnotation as! KMTableAnnotation, point: pagePoint) listView.needsDisplay = true return } var pagePoint: NSPoint = .zero if let page = self.listView.pageAndPoint(&pagePoint, for: theEvent, nearest: true) { let anno = page.annotation(at: pagePoint) let item1 = NSMenuItem(title: NSLocalizedString("Delete", comment: ""), action: #selector(menuItemActionMeasureDelete), target: self) item1.representedObject = anno let item2 = NSMenuItem(title: NSLocalizedString("Edit Note", comment: ""), action: #selector(menuItemActionMeasureEditNote), target: self) item2.representedObject = anno let item3 = NSMenuItem(title: NSLocalizedString("Settings", comment: ""), action: #selector(menuItemActionMeasureSetting), target: self) item3.representedObject = anno if let data = anno as? CPDFPolygonAnnotation { // 多变形 currentMenu.removeAllItems() currentMenu.insertItem(item1, at: 0) currentMenu.insertItem(item2, at: 1) currentMenu.insertItem(item3, at: 2) return } if let data = anno as? CPDFPolylineAnnotation { currentMenu.removeAllItems() currentMenu.insertItem(item1, at: 0) currentMenu.insertItem(item2, at: 1) currentMenu.insertItem(item3, at: 2) return } if let data = anno as? CPDFLineAnnotation, data.isMeasure { currentMenu.removeAllItems() currentMenu.insertItem(item1, at: 0) currentMenu.insertItem(item2, at: 1) currentMenu.insertItem(item3, at: 2) return } } if (listView.toolMode == .selectToolMode){ currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.printingMenu(), at: 3) currentMenu.insertItem(self.setTTSStype(), at: 3) currentMenu.insertItem(self.setCropStype(), at: 3) currentMenu.insertItem(self.setSnapshotStype(), at: 3) let export = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: nil, target: self) export.submenu = self.exportMenu() currentMenu.insertItem(export, at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) if listView.activeAnnotation == nil{ currentMenu.insertItem(self.setAnnotationToolStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) } currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 3) currentMenu.insertItem(self.addReadModelStype(), at: currentMenu.items.count - 3) currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.setAITranslateStype(), at: 0) currentMenu.insertItem(self.setAIProofreadStype(), at: 0) currentMenu.insertItem(self.setAIRewriteStype(), at: 0) return } if (listView.toolMode == .moveToolMode || listView.toolMode == .magnifyToolMode){ currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.setTTSStype(), at: 0) currentMenu.insertItem(self.setCropStype(), at: 0) currentMenu.insertItem(self.setSnapshotStype(), at: 0) currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.addOutlineStype(), at: 0) currentMenu.insertItem(self.addBookmarkMenu(), at: 0) if listView.activeAnnotation == nil{ currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.setAnnotationToolStype(), at: 0) } currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.setAITranslateStype(), at: 0) currentMenu.insertItem(self.setAIProofreadStype(), at: 0) currentMenu.insertItem(self.setAIRewriteStype(), at: 0) return } if currentMenu.items.count > 3 { currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 3) currentMenu.insertItem(self.addReadModelStype(), at: currentMenu.items.count - 3) } if listView.currentSelection != nil && listView.activeAnnotations.count < 1{ if listView.currentSelection.selectionType() == .text { currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.setSearchBaiduStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.setLookUpStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.addOutlineStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.setAnnotationToolStype(), at: 3) currentMenu.insertItem(self.setTTSStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) currentMenu.insertItem(self.setShareStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) } currentMenu.insertItem(self.enterAnnotationStype(), at: 3) currentMenu.insertItem(NSMenuItem.separator(), at: 3) if listView.currentSelection.selectionType() == .image{ currentMenu.insertItem(NSMenuItem.separator(), at: 6) currentMenu.insertItem(self.addOutlineStype(), at: 6) currentMenu.insertItem(NSMenuItem.separator(), at: 6) currentMenu.insertItem(self.setAnnotationToolStype(), at: 6) } if listView.currentSelection.selectionType() == .text { currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count) currentMenu.insertItem(self.setTranslateStype(), at: currentMenu.items.count) currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count) } } if listView.activeAnnotation != nil || isMoveSelectAnno { if let data = self.listView.activeAnnotation?.type?.lowercased(), data == "stamp"{ currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 15) currentMenu.insertItem(self.enterAnnotationStype(), at: currentMenu.items.count - 15) currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 15) }else{ currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 15) currentMenu.insertItem(self.enterAnnotationStype(), at: currentMenu.items.count - 15) if let anno = self.listView.activeAnnotation, anno.isKind(of: CPDFStampAnnotation.self) { } else { currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 15) currentMenu.insertItem(self.setShareStype(), at: currentMenu.items.count - 15) } currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count - 15) } } if listView.activeAnnotation == nil && listView.currentSelection == nil{ currentMenu.insertItem(NSMenuItem.separator(), at: currentMenu.items.count) if(listView.toolMode == .selectToolMode) { if NSIsEmptyRect(listView.currentSelectionRect()) { currentMenu.insertItem(self.zoomSelectionMenuItem(), at: 0) currentMenu.insertItem(NSMenuItem.separator(), at: 0) } currentMenu.insertItem(self.printingMenu(), at: 0) currentMenu.insertItem(self.setTTSStype(), at: 0) currentMenu.insertItem(self.setCropStype(), at: 0) currentMenu.insertItem(self.setSnapshotStype(), at: 0) let export = NSMenuItem(title: NSLocalizedString("Export", comment: ""), action: nil, target: self) export.submenu = self.exportMenu() currentMenu.insertItem(export, at: currentMenu.items.count) }else{ currentMenu.insertItem(NSMenuItem.separator(), at: 2) currentMenu.insertItem(self.setTTSStype(), at: 2) currentMenu.insertItem(self.setCropStype(), at: 2) currentMenu.insertItem(self.setSnapshotStype(), at: 2) currentMenu.insertItem(NSMenuItem.separator(), at: 2) currentMenu.insertItem(self.addOutlineStype(), at: 2) currentMenu.insertItem(NSMenuItem.separator(), at: 2) currentMenu.insertItem(self.enterAnnotationStype(), at: 2) currentMenu.insertItem(NSMenuItem.separator(), at: 2) if(currentMenu.items.count > 4) { currentMenu.insertItem(NSMenuItem.separator(), at: 5) } if(currentMenu.items.count > 5) { currentMenu.insertItem(self.addBookmarkMenu(), at: 6) } currentMenu.insertItem(self.setAutoScrollStype(), at: currentMenu.items.count) } currentMenu.insertItem(self.setAnnotationToolStype(), at: 5) } currentMenu.insertItem(NSMenuItem.separator(), at: 0) currentMenu.insertItem(self.setAITranslateStype(), at: 0) currentMenu.insertItem(self.setAIProofreadStype(), at: 0) currentMenu.insertItem(self.setAIRewriteStype(), at: 0) for item in currentMenu.items { if (item.action == NSSelectorFromString("menuItemClick_HidenorShowNote:")) { // 显示与隐藏注释 item action 截取 item.action = #selector(menuItemClick_HidenorShowNote) item.target = self break } } } func pdfListViewAddAnnotations(_ pdfListView: CPDFListView!, forAdd annotations: [CPDFAnnotation]!, in pdfPage: CPDFPage!) { var addRedact = false for anno in annotations { if (anno.isKind(of: CPDFRedactAnnotation.self)) { addRedact = true } else if anno is CPDFSquareAnnotation || anno is CPDFCircleAnnotation { anno.contents = pdfPage?.string(for: anno.bounds) ?? "" } } self.model.hasAddRedact = addRedact if self.listView.toolMode == .moveToolMode { self.listView.toolMode = .textToolMode self.listView.annotationType = .unkown } if (self.model.rightMouseEventing) { self.model.rightMouseEventing = false } self.leftSideViewController.refreshUIForAddAnnotation(annos: annotations, page: pdfPage) } func pdfListViewRemoveAnnotations(_ pdfListView: CPDFListView!, forRemove annotations: [CPDFAnnotation]!, in pdfPage: CPDFPage!) { self.leftSideViewController.annoList_refreshUIForDeleteAnnotations(annos: annotations, page: pdfPage) } func pdfListViewDidSelectionEnd(_ pdfListView: CPDFListView!) { if (!self.listView.isEqual(to: pdfListView)) { return } if (self.listView.toolMode != .selectToolMode) { return } } func pdfListViewKeyDowClosePanel(_ speedy: CPDFViewSidebarSpeedMode, event theEvent: NSEvent!) { if(speedy == .right) { self.toggleRightPane() } else if (speedy == .left) { self.menuItemAction_hiddenLeftSide(speedy) } } func pdfListViewEventMarkupColor(with annotation: CPDFAnnotation!) -> [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 pdfListView(_ sender: CPDFListView!, showSnapshotAtPageNumber pageNum: Int, for rect: NSRect, scaleFactor: CGFloat, autoFits: Bool) { let swc = KMSnapshotWindowController(windowNibName: "SnapshotWindow") swc.delegate = self swc.setPdfDocument(self.listView.document, goToPageNumber: pageNum, rect: rect, scaleFactor: scaleFactor, autoFits: autoFits) swc.forceOnTop = self.interactionMode != .normal self.myDocument?.addWindowController(swc) } func pdfListView(_ pdfView: CPDFListView!, documentDataDidChanged docData: Any!, withInfo info: [AnyHashable : Any]!) { if let data = info?[CPDFListView.outlineKey] as? Bool, data { // 大纲改变 guard let ol = docData as? CPDFOutline else { return } let add = info?[CPDFListView.outlineAddKey] as? Bool ?? false let remove = info?[CPDFListView.outlineRemoveKey] as? Bool ?? false if add { self.leftSideViewController.addOutlineAfter(ol) } if remove { self.leftSideViewController.removeOutlineAfter(ol) } let demote = info?[CPDFListView.outlineDemoteKey] as? Bool ?? false let promote = info?[CPDFListView.outlinePromoteKey] as? Bool ?? false if demote { self.leftSideViewController.demoteOutlineAfter(ol) } if promote { self.leftSideViewController.promoteOutlineAfter(ol) } } } //TextEdit func pdfListViewDidTextFontChanged(_ pdfListView: CPDFListView!) { } func pdfListViewDidTextColorChanged(_ pdfListView: CPDFListView!, with color: NSColor!) { } 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() } func tableMenu(_ menu: NSMenu, withTable table: KMTableAnnotation, point: CGPoint) -> NSMenu { if table.currentCell.row >= 0 && table.currentCell.column >= 0 { let itemTitles = ["Edit", "", "Add Row Above", "Add Row Below", "", "Add Column Before", "Add Column After", "", "Delete Row", "Delete Column", "Delete Table", "Cut", "Copy", "Paste", "Paste and Match Style", "Delete Cell Contents", "Clear All"] let actions = ["formAnnotTextEdit:", "", "addRowAbove:", "addRowBelow:", "", "addColumnBefore:", "addColumnAfter:", "", "deleteRow:", "deleteColumn:", "deleteTabel", "cutCell:", "copyCell:", "pasteCell:", "pasteAndMatchStyle:", "deleteCellContents:", "clearAll:"] for i in 0..= 5 { item!.action = nil } else if (path2 as AnyObject).lineJoinStyle == NSBezierPath.LineJoinStyle.bevel && table.footerCount() >= 5 { item!.action = nil } } item!.title = NSLocalizedString(item!.title, comment: "") item!.representedObject = NSValue(point: point) menu.insertItem(item!, at: i) } } } else { let itemTitles = ["Cut", "Copy", "Paste", "Delete"] let actions = ["cut:", "copy:", "paste:", "delete:"] for i in 0..= 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: - KMNThumbnailBaseViewDelegate extension KMMainViewController: KMNThumbnailBaseViewDelegate { func clickThumbnailViewControlle(pageEditVC:KMNThumbnailBaseViewController?,currentIndex:Int) { exitPageEditMode() viewManager.isPageEditMode = false pdfToolbarController?.reloadPageEditView() } 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() } } 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 { let message = KMNCustomAlertView.alertView(message: KMLocalizedString("This page has been bookmarked"), type: .normal_custom, fromView: self.view, point:CGPointMake(self.view.frame.origin.x + self.view.frame.size.width/2, self.view.bounds.size.height - 30)) } } } } //MARK: - //MARK: - //MARK: - //MARK: - 旧代码,需要用到的内容需要拖出来,写好注释 extension KMMainViewController { func awakeFromNibFunction() { self.addBackgroundMaskView() listView.delegate = self listView.pdfListViewDelegate = self if (document != nil) { self.listView.document = self.document self.listView.document?.delegate = self let autoScale = listView.autoScales if !autoScale { listView.scaleFactor = 1.0 } } self.initPDFLeftViewVC() self.leftSideViewController.mainViewController = self } func viewDidAppearFunction() { //春季活动 if ((KMAdvertisementManager.manager.info.popWindowContent) != nil) { if KMAdvertisementManager.manager.info.popWindowContent!.content!.count > 0 { let info = KMAdvertisementManager.manager.info.popWindowContent!.content?.first if KMAdvertisementManager.checkAdvertisementValid(info!) { self.loadRecommondPopWindow() } } } self.addEventMonitor() self.view.window?.makeFirstResponder(self.listView) // 更新属性页面的信息 NotificationCenter.default.post(name: KMInfoWindowC.windowDidBecomeMainNotification, object: self.myDocument) self.interfaceThemeDidChanged(self.view.window?.appearance?.name ?? (NSApp.appearance?.name ?? .aqua)) if (self.document == nil) { return } if (self.document == nil || self.document!.isLocked == false) { self.loadFunctionGuide() } if (self.document?.isLocked == false) { if self.model.needConvertNotes && self.tabViewIsDragging() == false { self.showConvertNotesProgress() } return } if (self.view.window == nil) { return } if (self.model.password != nil) { if let data = self.listView.document?.unlock(withPassword: self.model.password), data { self.model.isSaveKeyChain = false if self.model.needConvertNotes && self.tabViewIsDragging() == false { self.showConvertNotesProgress() } return } } DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3) { if self.view.window != nil && self.tabViewIsDragging() == false { self.passwordWindow = KMPasswordInputWindow.openWindow(window: self.view.window!, url: self.document!.documentURL) { [weak self] result , password in if (result == .cancel) { (self?.myDocument as? KMMainDocument)?.browser?.closeTab() return } self?.model.isSaveKeyChain = true self?.listView.document = self?.document self?.document?.unlock(withPassword: password) } } else { if self.model.needConvertNotes && self.tabViewIsDragging() == false { self.showConvertNotesProgress() } } } } func viewWillDisappearFunction() { if self.interactionMode != .presentation { self.removeEventMonitor() } } func viewWillLayoutFunction() { if (KMTools.isFullScreen(self.view.window ?? NSWindow())) { // 全屏 self.listView.backgroundColor = KMPreferenceManager.shared.displayBackgroundFullScreenColor } else { self.listView.backgroundColor = KMPreferenceManager.shared.displayBackgroundNormalColor } if let guideWC = self.guideInfoWindowController{ 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 guideWC.show() } } func viewDidLoadOld() { mwcFlags.settingUpWindow = 1 self.srHanddler.pdfView = self.listView self.initToolbar() if (UserDefaults.standard.object(forKey: CPDFOfficeLeftSidePaneWidthKey) != nil) { UserDefaults.standard.set(256, forKey: CPDFOfficeLeftSidePaneWidthKey) UserDefaults.standard.synchronize() } if (UserDefaults.standard.object(forKey: CPDFOfficeRightSidePaneWidthKey) != nil) { UserDefaults.standard.set(256, forKey: CPDFOfficeRightSidePaneWidthKey) UserDefaults.standard.synchronize() } if (KMPreferenceManager.shared.openLastUnlockedDocumentWhenAppStart) { if (self.listView.document != nil) { let pageNumber = KMPreferenceManager.shared.getPageNumber(forKey: self.listView.document?.documentURL.path ?? "") let pageScale = KMPreferenceManager.shared.getPageScale(forKey: self.listView.document?.documentURL.path ?? "") if (pageNumber != nil && pageNumber! >= 0 && pageNumber! < (self.listView.document?.pageCount ?? 0)) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { if (pageScale != nil) { self.listView.scaleFactor = CGFloat(pageScale!) } self.listView.go(toPageIndex: pageNumber!, animated: false) } } else { self._goToFirstPageForFristAppear() } } } else { self._goToFirstPageForFristAppear() } NotificationCenter.default.addObserver(self, selector: #selector(rename(_:)), name: NSNotification.Name.init(rawValue: "KMTabControllerRename"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(closeTab(_:)), name: NSNotification.Name.init(rawValue: "KMTabControllerCloseTabs"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(showInFinder(_:)), name: NSNotification.Name.init(rawValue: "KMTabControllerShowInFinder"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(preferenceDidChangeNotification), name: KMPreferenceManager.didChangeNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(documentDidUnlockNotification), name: Notification.Name("CPDFDocumentDidUnlockNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(annotationsAttributeHasChange), name: NSNotification.Name.CPDFListViewAnnotationsAttributeHasChange, object:nil) NotificationCenter.default.addObserver(self, selector: #selector(applicationWillTerminateNotification), name: NSApplication.willTerminateNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(CPDFDocumentPageCountChangedNotification), name: NSNotification.Name.init(rawValue: "CPDFDocumentPageCountChangedNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(CEditPDFToolModeChangeStateUnkownNotification), name: Notification.Name.init("CEditPDFToolModeChangeStateUnkown"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(handlePageChangedNotification), name: NSNotification.Name.CPDFViewPageChanged, object: self.listView) NotificationCenter.default.addObserver(self, selector: #selector(handleDisplayBoxChangedNotification), name: NSNotification.Name.CPDFViewDisplayBoxChanged, object: self.listView) NotificationCenter.default.addObserver(self, selector: #selector(didAddContentViewNotification), name: NSWindow.didAddContentViewNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(addAutoSaveEvent), name: AutoSaveManager.kTimeValueChangedNotificationName, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(didRemoveAnnotationNotification), name: NSNotification.Name.CPDFPageDidRemoveAnnotation, object: nil) Task { self.addAutoSaveEvent() } self.closeRightPane() self.addKeyEventMonitor() self.addAdsBannerView() var snapshotSetups: NSArray? if KMPreferenceManager.shared.rememberSnapshot { if let fileUrl = (self.myDocument as? KMMainDocument)?.fileURL { snapshotSetups = SKBookmarkController.shared().snapshotsForRecentDocument(at: fileUrl) as NSArray? } } if let cnt = snapshotSetups?.count, cnt > 0 { if let data = self.listView.document?.isLocked, data { self.savedNormalSetup.setObject(snapshotSetups as Any, forKey: "snapshots" as NSCopying) } else { self.showSnapshots(setups: snapshotSetups) } } let readModel = UserDefaults.standard.bool(forKey: "kKMPDFViewIsReadMode") if readModel == true { self.openPDFReadMode() } let hasWindowSetup = savedNormalSetup.count > 0 if UserDefaults.standard.dictionary(forKey: KMDefaultPDFDisplaySettingsKey) != nil { let pdfSettings: NSDictionary = hasWindowSetup ? savedNormalSetup : UserDefaults.standard.dictionary(forKey: KMDefaultPDFDisplaySettingsKey)! as NSDictionary self.applyPDFSettings(pdfSettings) } else { self.applyPDFSettings(savedNormalSetup) } //文字 let fontManager = NSFontManager.shared fontManager.target = self fontManager.action = #selector(changeFont(_:)) } //MARK: - PDFListView func initPDFLeftViewVC() { var frame = self.leftView.frame frame.size.width += 44 self.leftView.frame = frame leftSideViewController.isFirst = true leftSideViewController.listView = self.listView leftSideViewController.view.frame = CGRect(x: 0, y:0 , width: self.leftView.frame.size.width, height: self.leftView.frame.size.height) leftSideViewController.view.autoresizingMask = [.height,.width] leftSideViewController.delegate = self self.leftView.addSubview(leftSideViewController.view) } func addAdsBannerView() { #if VERSION_FREE if !IAPProductsManager.default().isAvailableAllFunction(){ guard let document = self.listView.document else { return } if !document.isLocked { } NotificationCenter.default.addObserver(self, selector: #selector(purchaseStateUpdateNoti), name: NSNotification.Name(rawValue: "KMIAPProductPurchasedNotification"), object: nil) NotificationCenter.default.addObserver(self, selector: #selector(purchaseStateUpdateNoti), name: NSNotification.Name(rawValue: "kDeviceActivateNotification"), object: nil) } #endif } // MARK: Private Methods private func _isArabicLanguage() -> Bool { return NSLocalizedString("Right click a color and select “Change Color...“.", comment: "") == "انقر بزر الماوس الأيمن فوق اللون وحدد \"تغيير اللون...\"." } internal func removeNotifications() { NotificationCenter.default.removeObserver(self) self.leftSideViewController.clearAnnotationFilterData() self.leftSideViewController.clearNotification() } func checkShouldAutoOpenLeftVC() { if KMPreference.shared.showLeftSideBar == false { return } if self.model.leftPanelOpen { return } let readModel = UserDefaults.standard.bool(forKey: "kKMPDFViewIsReadMode") if readModel == true { return } DispatchQueue.main.async { self.leftSideViewController.showThumbnail() } } func applyLeftSideWidth(_ leftSideWidth: CGFloat, rightSideWidth: CGFloat) -> Void { } 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) } } @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() { let toolMode = self.listView.toolMode if toolMode != .measureToolMode { return } let type = self.listView.annotationType if type == .line { self.distanceMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .polyLine { self.perimeterMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .polyGon { self.areaMeasureInfoWindowController?.window?.orderFront(nil) } else if type == .square { self.areaMeasureInfoWindowController?.window?.orderFront(nil) } } // MARK: - 标记密文 func enterRedact() { if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.kEventName = "Reading_Redact_BuyNow" winC?.showWindow(nil) return } if self.listView.document?.allowsPrinting == false || self.listView.document?.allowsCopying == false { Task { _ = await KMAlertTool.runModel(message: KMLocalizedString("This is a secured document. Editing is not permitted.")) } return } if self.hasEnterRedact() { self.exitRedact() return } self.leftSideViewController.thumbnailTableView.isEnabled = false self.leftSideViewController.tocOutlineView.isEnabled = false self.leftSideViewController.noteOutlineView.isEnabled = false self.leftSideViewController.findTableView.isEnabled = false self.leftSideViewController.groupedFindTableView.isEnabled = false self.leftSideViewController.snapshotTableView.isEnabled = false 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() } } NSColorPanel.shared.showsAlpha = false redactController = KMPDFRedactViewController(url: self.listView.document!.documentURL, password: self.listView.document?.password) self.addChild(redactController) redactController.view.autoresizingMask = [.width, .height] self.listView.isHidden = true redactController.scaleFactor = self.listView.scaleFactor redactController.titleBack = { [weak self] title in self?.view.window?.title = title } redactController.callback = { [weak self] result, currentPageIndex, saveResult, saveUrl in self?.listView.go(toPageIndex: self!.redactController.redactPdfView.currentPageIndex, animated: false) if result == false { // 退出 self?.exitRedact() return } let controller = self?._getPDFRedactController() controller?.redactPdfView.newAddAnnotation.removeAll() self?.exitRedact() if saveResult { let newDocument = CPDFDocument(url: saveUrl) if let data = newDocument?.isLocked, data { newDocument?.unlock(withPassword: self?.listView.document?.password ?? "") } self?.document = newDocument self?.listView.document = newDocument self?.listView.layoutDocumentView() } } redactController.setCurrentPageIndex(self.listView.currentPageIndex) } func exitRedact() { self.leftSideViewController.thumbnailTableView.isEnabled = true self.leftSideViewController.tocOutlineView.isEnabled = true self.leftSideViewController.noteOutlineView.isEnabled = true self.leftSideViewController.findTableView.isEnabled = true self.leftSideViewController.groupedFindTableView.isEnabled = true self.leftSideViewController.snapshotTableView.isEnabled = true let controller = self._getPDFRedactController() if let data = controller { if data.redactPdfView.newAddAnnotation.count > 0 { KMAlertTool.runModel(message: "", informative: KMLocalizedString("There are unapplied redactions in this file. Exit will not save redaction."), buttons: [KMLocalizedString("Exit"), KMLocalizedString("Cancel")]) { response in if response == .alertFirstButtonReturn { controller?.redactPdfView.newAddAnnotation.removeAll() self.exitRedact() } } return } } NSColorPanel.shared.showsAlpha = true controller?.redactPdfView.resignMonitor() controller?.view.removeFromSuperview() controller?.removeFromParent() self.listView.isHidden = false self.listView.annotationType = .unkown } func hasEnterRedact() -> Bool { return self._getPDFRedactController() != nil } //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: self?.showAllConvertWindow(convertT: .Word) } 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: - 页面编辑 open func enterPageEdit(_ pages: [Int] = []) { if let doc = self.listView.document { if doc.allowsCopying == false || doc.allowsPrinting == false { KMBaseWindowController.checkPassword(url: doc.documentURL, type: .owner) { result, pwd in if result && pwd.isEmpty == false { self.listView.document?.unlock(withPassword: pwd) Task { @MainActor in self.enterPageEdit(pages) } } else { self.exitPageEdit() } } return } } //选中page var tPages = pages if tPages.count == 0 { if self.leftSideViewController.type.methodType == .Thumbnail { tPages = self.leftSideViewController.thumb_fetchSelectedRows() ?? [self.listView.currentPageIndex] } } if (hasEnterPageEdit()) { exitPageEdit() return } let controller = KMPDFEditViewController(self.listView.document) controller.selectedPages = tPages controller.listView = self.listView self.addChild(controller) controller.view.autoresizingMask = [.width,.height] self.listView.isHidden = true controller.itemClick = { [weak self] index, params in if (index == 1) { /// 双击退出 self?.enterEditMode(self!.leftSideViewController, []) DispatchQueue.main.async { let pageIndex: Int = params.first as! Int self?.listView.go(toPageIndex: pageIndex, animated: true) } } else if (index == 2) { // 打印 self?.showPrintWindow(pageRange: KMPrintPageRange(type: .custom, selectPages: params.first as! [Int])) } } controller.documentEditedCallback = { [weak self] params in self?.recordIsPDFDocumentEdited() } controller.selectionDidChange = { selectedIndexs in var indexSet = IndexSet() for indexPath in selectedIndexs { indexSet.insert(indexPath.item) } if indexSet.count != 0 { } } } open func exitPageEdit() { let editController = getPDFEditController() if (editController == nil) { return } self.listView.annotationType = .highlight // FIXME: - sdk修复插入特定文档crash后,这行代码可以去掉 self.leftSideViewController.model.insertedDocumentSet.formUnion(editController?.model.insertedDocumentSet ?? []) editController?.view.removeFromSuperview() editController?.removeFromParent() self.listView.isHidden = false self.listView.layoutDocumentView() self.view.window?.makeFirstResponder(self.listView) self.listView.annotationType = .unkown self.listView.go(toPageIndex: editController!.listViewCurrentIndex, animated: false) if let data = editController?.isEdited, data { self.leftSideViewController.reloadThumbnailDataIfNeed() self.leftSideViewController.note_reloadDataIfNeed() self.leftSideViewController.refreshUIOfOutlineIfNeed() self.leftSideViewController.refreshUIOfSeachListIfNeed() self.leftSideViewController.refreshUIOfBookmarkIfNeed() } } open func hasEnterPageEdit() -> Bool { return self.getPDFEditController() != nil } // MARK: - 数字签名 func hasShowDigitalSign() -> Bool { return self.digitalSignController?.view.superview != nil } func canEnterDigitalSign() -> Bool { guard let doc = self.listView.document else { return false } return doc.allowsPrinting && doc.allowsCopying } func enterDigitalSign() { self.listView.toolMode = .textToolMode if self.hasShowDigitalSign() { self.exitDigitalSign() } else { if self.needSaveDocument() { self.saveDocumentWithProgressAlert { [unowned self] params in if (self.listView.document != nil) { self.showDigitalSignWindow(withFilePathURL: self.listView.document.documentURL) } } return } if (self.listView.document != nil) { self.showDigitalSignWindow(withFilePathURL: self.listView.document.documentURL) } } } func exitDigitalSign() { self.digitalSignController?.view.removeFromSuperview() // KMDocumentDigitalSignToolbarItemIdentifier } func showDigitalSignWindow(withFilePathURL fileURL: URL) { if !IAPProductsManager.default().isAvailableAllFunction(){ let winC = KMPurchaseCompareWindowController.sharedInstance() winC?.kEventName = "Reading_DigitalSign_BuyNow" winC?.showWindow(nil) return } if hasShowDigitalSign() { self.exitDigitalSign() } var currentPageIndex = listView.document?.index(for: listView.currentPage()) ?? 0 var password: String = "" password = listView.document?.password ?? "" digitalSignController = KMPDFDigitalSignViewController() digitalSignController?.currentPageIndex = Int(currentPageIndex) digitalSignController?.url = listView.document?.documentURL digitalSignController?.password = password digitalSignController?.scaleFactor = listView.scaleFactor digitalSignController?.titleChangeBlock = { title, index in currentPageIndex = UInt(index) } digitalSignController?.buttonActionBlock = { [weak self] type, isChanged in if type == .cancel { if let page = self?.listView.document?.page(at: currentPageIndex) { self?.listView.go(to: page) } self?.exitDigitalSign() } } } // MARK: - Toolbar func toolbarItemClickForExitMode(_ toolbarItem: KMToolbarItemView) { if(toolbarItem.itemIdentifier != KMDocumentPageToolbarItemIdentifier) { if (hasEnterPageEdit()) { self.exitPageEdit() } } if toolbarItem.itemIdentifier != KMDocumentRedactToolbarItemIdentifier { if self.hasEnterRedact() { self.exitRedact() } } if toolbarItem.itemIdentifier != KMDocumentDigitalSignToolbarItemIdentifier { if self.hasShowDigitalSign() { self.exitDigitalSign() } } if toolbarItem.itemIdentifier != KMDocumentEditToolbarItemIdentifier && toolbarItem.itemIdentifier != KMRightControlToolbarItemIdentifier && toolbarItem.itemIdentifier != KMLeftControlToolbarItemIdentifier { } } // MARK: - Private Methods private func getPDFEditController() -> KMPDFEditViewController? { var editController: KMPDFEditViewController? for controller in self.children { if (controller.isKind(of: KMPDFEditViewController.self)) { editController = (controller as! KMPDFEditViewController) break } } return editController } private func _getPDFRedactController() -> KMPDFRedactViewController? { var controller: KMPDFRedactViewController? for childC in self.children { if (childC.isKind(of: KMPDFRedactViewController.self)) { controller = (childC as! KMPDFRedactViewController) break } } return controller } private func addBackgroundMaskView() { self.removeBackgroundMaskView() } private func removeBackgroundMaskView() { } private func _goToFirstPageForFristAppear() { DispatchQueue.main.asyncAfter(wallDeadline: .now()+0.1) { self.listView.go(toPageIndex: 0, animated: false) } } 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 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: - Secure 【安全】 public func showSecureLimitTip() { self.hiddenSecureLimitTip() if self.secureAlertView == nil { self.secureAlertView = KMSecureAlertView() self.secureAlertView?.show(in: self.listView) self.secureAlertView?.closeAction = { [unowned self] view in self.hiddenSecureLimitTip() self.removeFromAlertView() self.showFormAlertView() } self.secureAlertView?.passwordAction = { [unowned self] view in self.removeOwnerPassword() self.removeFromAlertView() self.showFormAlertView() } } } func removeOwnerPassword() { guard let doc = self.listView.document else { NSSound.beep() return } if doc.allowsCopying && doc.allowsPrinting { NSSound.beep() return } _ = KMPasswordInputWindow.openWindow(window: self.view.window!, type: .owner, url: doc.documentURL) { [weak self] result, password in if result == .cancel { /// 关闭 return } /// 解密成功 self?.hiddenSecureLimitTip() self?.model.isSaveKeyChain = false self?.listView.document?.unlock(withPassword: password) } } public func hiddenSecureLimitTip() { self.secureAlertView?.removeFromSuperview() self.secureAlertView = nil } //MARK: - Form func showFormAlertView() { if (formAlertView == nil) { formAlertView = KMFormAlertView() formAlertView?.isCloseSecureView = self.secureAlertView != nil ? false : true formAlertView?.showInView(self.listView) } else { self.removeFromAlertView() } } func removeFromAlertView() { formAlertView?.removeFromSuperview() formAlertView = nil } override func mouseMoved(with event: NSEvent) { self.view.window?.mouseMoved(with: event) } func savePageNumberIfNeed() { if (KMPreferenceManager.shared.openLastUnlockedDocumentWhenAppStart) { 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 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: - 显示加密弹窗 public func showSecureWindow(_ url: URL) { 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: - 保存文档 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: - 选择 PDFDisplay 模式 public func setPDFDisplay(pdfViewMode: CPDFDisplayViewMode) { listView.setDisplay(pdfViewMode) } // 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 } } internal func createPdf(index:Int) { } // 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 } } func addKeyEventMonitor() { if (self.keyEventMonitor != nil) { self.removeKeyEventMonitor() } keyEventMonitor = NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [weak self] event in if event.keyCode == 53 { if let data = self?.interactionMode, data == .presentation { // 幻灯片模式下 self?.exitFullScreen() return event } if self?.listView.toolMode == .editPDFToolMode { if self != nil { //使用editingSelectionString获取内容文字 if self!.listView.editingAreas() != nil { if self!.listView.editingAreas().count > 0 && self!.listView.isEditable() { self!.listView.clearEditingSelectCharItem() } else if self!.listView.editingAreas().count > 0 { if self?.listView.annotationType == .addImage || self?.listView.annotationType == .addText { } self?.listView.endEditIsRemoveBlock(with: self!.listView.editingAreas().first as? CPDFEditArea) self?.listView.updateEditing([]) self?.listView.isEditImage = false self?.listView.setNeedsDisplayPageViewFor(self!.listView.currentPage()) if self?.listView.annotationType == .addImage { self?.listView.change([.text, .image]) } self?.listView.annotationType = .editTextImage self?.closeRightPane() } else if(self?.listView.annotationType == .addImage || self!.listView.annotationType == .addText) { if self?.listView.annotationType == .addImage || self?.listView.annotationType == .addText { } self?.listView.setShouAddEdit([]) self?.listView.change([.text, .image]) self?.listView.annotationType = .editTextImage self?.closeRightPane() } } else { if self?.listView.annotationType == .addImage || self?.listView.annotationType == .addText { } } } } } else { if let data = self?.interactionMode, data == .presentation { // 幻灯片模式下 self?.listView.keyDown(with: event) return event } else { let cmd = event.modifierFlags.contains(.command) let shift = event.modifierFlags.contains(.shift) if event.keyCode == 6 { // z let editPDFIng = self?.listView.isEditing() ?? false if cmd && shift { // 恢复 let can = self?.listView.canEditTextRedo() ?? false if can == false { return event } if editPDFIng { _ = CustomAlertView.alertView(message: NSLocalizedString("Redo", comment: ""), fromView: self!.view, withStyle: .black) } } else if cmd { // 撤回 let can = self?.listView.canEditTextUndo() ?? false if can == false { return event } if editPDFIng { _ = CustomAlertView.alertView(message: NSLocalizedString("Undo", comment: ""), fromView: self!.view, withStyle: .black) } } } } } return event } } func removeKeyEventMonitor() { if (self.keyEventMonitor != nil) { KMPrint("removeKeyEventMonitor 已移除事件监听") NSEvent.removeMonitor(self.keyEventMonitor as Any) self.keyEventMonitor = nil } } 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 } public func clearSecureOptions() { self._secureOptions = nil self.documentAttribute = nil } public func recordRemoveSecureFlag() { self._removeSecureFlag = true self.clearSecureOptions() self.recordIsPDFDocumentEdited(type: .removePassword) self._needSave = true } public func clearRemoveSecureFlag() { self._removeSecureFlag = false } public func clearSaveWatermarkFlag() { km_synchronized(self) { self._saveWatermarkFlag = false } } public func recordIsPDFDocumentEdited(type: KMSubscribeWaterMarkType = .none) { km_synchronized(self) { self.model.isPDFDocumentEdited = true if type == .editText || type == .editImage { self.leftSideViewController.updateThumbnail(at: self.listView.currentPageIndex) } 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) } } } func dealDocumentDidLoaded() { self.removeBackgroundMaskView() if (!self.listView.document!.allowsCopying || !self.listView.document!.allowsPrinting) { self.showSecureLimitTip() } if self.model.needConvertNotes { self.showConvertNotesProgress() } if (self._documentFirstLoad) { self.checkShouldAutoOpenLeftVC() if (KMPreferenceManager.shared.openLastUnlockedDocumentWhenAppStart) { let pageNumber = KMPreferenceManager.shared.getPageNumber(forKey: self.listView.document?.documentURL.path ?? "") let pageScale = KMPreferenceManager.shared.getPageScale(forKey: self.listView.document?.documentURL.path ?? "") if (pageScale != nil) { self.listView.scaleFactor = CGFloat(pageScale!) } if (pageNumber != nil && pageNumber! >= 0 && pageNumber! < (self.listView.document?.pageCount ?? 0)) { self.listView.go(toPageIndex: pageNumber!, animated: false) } else { self._goToFirstPageForFristAppear() } } else { self._goToFirstPageForFristAppear() } self._documentFirstLoad = false } } func tabViewIsDragging() -> Bool { let level = self.view.window?.level ?? .normal return level == .floating } // 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 = KMPreferenceManager.shared.savePasswordType 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 } } } 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() ?? "" } self.leftSideViewController.refreshUIForAnnoAttributeDidChange(anno, attributes: ["keyPath" : value]) } else { if value != CPDFAnnotationBoundsKey && value != CPDFAnnotationStartPointKey && value != CPDFAnnotationEndPointKey && value != CPDFAnnotationPathsKey { // 改变bounds(箭头、直线注释 开始点和结束点, 手绘注释的paths)的操作会卡顿,比如移动 self.leftSideViewController.refreshUIForAnnoAttributeDidChange(anno, attributes: ["keyPath" : value]) } } } } internal func applicationWillTerminateNotification(_ sender: Notification) { self.savePageNumberIfNeed() self.saveDocument() } func CPDFDocumentPageCountChangedNotification(_ sender: Notification) { self.leftSideViewController.refreshUIForAnnoAttributeDidChange(nil, attributes: nil) } func CEditPDFToolModeChangeStateUnkownNotification(_ sender: Notification) { var editSelectd = false if (self.listView.annotationType == .addText || self.listView.annotationType == .addImage) && self.listView.toolMode == .editPDFToolMode { editSelectd = true } if self.listView.toolMode == .editPDFToolMode { if editSelectd { } } } @objc func handlePageChangedNotification(_ sender: Notification) { if self.mwcFlags.isSwitchingFullScreen > 0 { return } let page = self.listView.currentPage() let pageIndex = page?.pageIndex() ?? 0 self.leftSideViewController.thumb_selectRowIndexsIfNeed(IndexSet(integer: IndexSet.Element(pageIndex))) self.leftSideViewController.thumbnailTableView.needsDisplay = true self.leftSideViewController.tocOutlineView.needsDisplay = true } @objc func handleDisplayBoxChangedNotification(_ sender: Notification) { self.leftSideViewController.reloadThumbnailDataIfNeed() } }