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