// // KMEditPDfHanddler.swift // PDF Reader Pro // // Created by tangchao on 2024/6/16. // import Cocoa @objc enum KMRightSideLastState: Int { case none = 0 case open = 1 case close = 2 } // EditPDF处理对象 class KMEditPDfHanddler: NSObject { weak var viewC: KMMainViewController? static let kRightSideLastStateKey = "KMRightSideLastStateKey" weak var listView: CPDFListView? { get { return self.viewC?.listView } } var annotationType: CAnnotationType { get { return self.listView?.annotationType ?? .unkown } } weak var rightViewC: KMRightSideViewController? { get { return self.viewC?.rightSideViewController } } var subViewType: RightSubViewType { get { return self.rightViewC?.subViewType ?? .None } } // var toolMode: CToolMode { // get { // return // } // } var isEditImage: Bool { get { return self.listView?.isEditImage ?? false } } var isEditing: Bool { get { return self.listView?.isEditing() ?? false } } var editingConfig: CPDFEditingConfig? { get { return self.listView?.editingConfig() } } var editingAreas: [CPDFEditArea] { get { return self.listView?.editingAreas() as? [CPDFEditArea] ?? [] } } var rightSideLastState: KMRightSideLastState { get { let state = KMDataManager.ud_integer(forKey: Self.kRightSideLastStateKey) return KMRightSideLastState(rawValue: state) ?? .none } set { KMDataManager.ud_set(newValue.rawValue, forKey: Self.kRightSideLastStateKey) } } private var startPoint_: NSPoint = .zero func enterEditPDF() { let toolMode = self.listView?.toolMode ?? .none if toolMode != .editPDFToolMode { // 退出 self.listView?.updateActiveAnnotations([]) self.listView?.setNeedsDisplayForVisiblePages() self.listView?.commitEditFormText() self.closeRightPane() self.hiddenPopWindow() self._removeNotification() return } self._addNotification() if self.rightSideLastState == .open { self.openRightPane() } else { self.closeRightPane() } self.listView?.updateActiveAnnotations([]) self.listView?.setNeedsDisplayForVisiblePages() self.listView?.commitEditFormText() self.listView?.annotationType = .editTextImage // 设置边框颜色 self.editingConfig?.editingBorderColor = .clear // 设置边框宽度 // self.editingConfig?.editingBorderWidth = 10 // 内容与边框的间距 // self.editingConfig?.editAreaMargin = .init(floatLiteral: 5) // 设置选中块边框颜色 // self.editingConfig?.editingSelectionBorderColor = .red // 显示hover边框 self.editingConfig?.isShowMouseAreaHover = true // hover // 边框宽度 // self.editingConfig?.mouseHoverBorderWidth = 1 // 边框颜色 self.editingConfig?.mouseHoverBorderColor = NSColor(hex: "#999999") // 边框虚线设置 self.editingConfig?.mouseHoverBorderDashPattern = [3,3,3] // 块填充颜色(拖拽中) // self.editingConfig?.editAreaMoveFillColor = .cyan // 是否显示位置辅助线 self.editingConfig?.isShowEditingAreaHover = true // 辅助线颜色 // self.editingConfig?.editingHoverBorderColor = .brown // 支持多选 self.editingConfig?.isSupportMultipleSelectEditingArea = true // 图片是否显示8个操作点 self.editingConfig?.isDrawRectWithDot = true } func openRightPane() { let state = self.rightSideLastState if state == .none || state == .open { self.viewC?.openRightPane() } } func closeRightPane() { self.rightViewC?.isHidden = true self.viewC?.closeRightPane() } func showPopWindow(positionRect: NSRect) { let show = KMPreference.shared.editPDFPopWindowIsShow if !show { return } let win = KMEditPDFPopToolBarWindow.shared self._kRemoveChildWindow(win) let areas = self.editingAreas win.isMultiple = areas.count > 1 var hasText = false var hasImage = false var fontColors: [NSColor] = [] for area in areas { if let data = area as? CPDFEditTextArea { hasText = true if let color = self.listView?.editingSelectionFontColor(with: data) { fontColors.append(color) } } if area is CPDFEditImageArea { hasImage = true } } var style: KMEditPDFToolbarStyle = [] if hasText { style.insert(.text) } if hasImage { style.insert(.image) } win.style = style win.model.editingAreas = areas win.model.fontColors = fontColors let area = (self.listView?.editingAreas().first as? CPDFEditArea) let areaBounds = (self.listView?.convert(area!.bounds, from: area!.page) as? NSRect) ?? .zero self.startPoint_ = self.listView?.documentView().documentVisibleRect.origin ?? .zero win.show(relativeTo: areaBounds, of: self.viewC!.listView, preferredEdge: .maxY) win.animator().alphaValue = 1 self._kAddchildwindow(win) win.itemClick = { [weak self] itemKey, obj in if itemKey == .color { self?.fontColorAction(color: obj as? NSColor) } else if itemKey == .fontStyle { self?.fontStyleAction(fontName: obj as? String) } else if itemKey == .fontAdd { self?.fontAddAction() } else if itemKey == .fontReduce { self?.fontReduceAction() } else if itemKey == .fontBold { self?.fontBoldAction() } else if itemKey == .fontItalic { self?.fontItalicAction() } else if itemKey == .textAlignment { self?.textAlignmentAction(align: obj as? NSTextAlignment ?? .left) } // 图片 else if itemKey == .leftRotate { self?.leftRotateAction() } else if itemKey == .rightRotate { self?.rightRotateAction() } else if itemKey == .reverseX { self?.reverseXAction() } else if itemKey == .reverseY { self?.reverseYAction() } else if itemKey == .crop { self?.cropAction() } else if itemKey == .replace { self?.replaceAction() } else if itemKey == .export { self?.exportAction() } // 对齐 else if itemKey == .alignmentLeft { self?.alignmentAction(align: .Left) } else if itemKey == .alignmentCenterX { self?.alignmentAction(align: .Horizontally) } else if itemKey == .alignmentRight { self?.alignmentAction(align: .Right) } else if itemKey == .alignmentjustifiedX { self?.alignmentAction(align: .DisHorizontally) } else if itemKey == .alignmentTop { self?.alignmentAction(align: .Top) } else if itemKey == .alignmentCenterY { self?.alignmentAction(align: .Vertical) } else if itemKey == .alignmentBottom { self?.alignmentAction(align: .Bottom) } else if itemKey == .alignmentjustifiedY { self?.alignmentAction(align: .DisVertical) } } // 显示新手引导 if let toolbarView = (win.contentViewController as? KMEditPDFPopToolBarController)?.toolbarView { self.showGuideView(toolbarView) } } func hiddenPopWindow() { let win = KMEditPDFPopToolBarWindow.shared win.orderOut(nil) win.setIsVisible(false) self._kRemoveChildWindow(win) } func showCropComfirmWindow() { let win = KMEditPDFPopToolBarWindow.shared let winFrame = win.frame let winC = KMEditPDFCropComfirmWindowController.shared let x = winFrame.origin.x + (NSWidth(winFrame)-84) * 0.5 let frame = NSMakeRect(x, winFrame.origin.y, 84, 44) winC.window?.setFrame(frame, display: true) winC.showWindow(nil) self._kAddchildwindow(winC.window!) winC.itemAction = { [weak self] idx, _ in self?.hiddenCropComfirmWindow() if idx == 0 { // 确认 self?.listView?.cropEditImageArea(self?.listView?.selectImageAreas, withBounds: self?.listView?.cropAreas.cropRect ?? .zero) self?.listView?.exitCrop(with: self?.listView?.selectImageAreas) self?.listView?.cropAreas = nil self?.listView?.isEditImage = false } else if idx == 1 { // 取消 self?.listView?.exitCrop(with: self?.listView?.selectImageAreas) self?.listView?.cropAreas = nil self?.listView?.isEditImage = false } Task { @MainActor [weak self] in if let data = self?.listView?.selectImageAreas { self?.showPopWindow(positionRect:data.bounds) } } } } func hiddenCropComfirmWindow() { let winC = KMEditPDFCropComfirmWindowController.shared winC.window?.orderOut(nil) winC.window?.setIsVisible(false) self._kRemoveChildWindow(winC.window) } func showGuideView(_ view: NSView) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { if KMGuideInfoWindowController.availableShow(.editPDFPopWindow) { var winFrame = self.viewC?.view.window?.frame ?? .zero winFrame.size.height -= 20 let area = (self.listView?.editingAreas().first as? CPDFEditArea) let areaBounds = (self.listView?.convert(area!.bounds, from: area!.page) as? NSRect) ?? .zero let guideWC = KMGuideInfoWindowController.currentWC() guideWC.type = .editPDFPopWindow var viewFrame = areaBounds let tmpY = areaBounds.origin.y+(areaBounds.size.height-KMEditPDFPopGuideView.kHeight+80) if tmpY < 50 { guideWC.editPDFPopWindowFlag = true viewFrame.origin.y += (areaBounds.size.height) viewFrame.origin.x += (areaBounds.size.width*0.5+KMEditPDFPopGuideView.kWidth*0.5) } else { guideWC.editPDFPopWindowFlag = false viewFrame.origin.y += (areaBounds.size.height-KMEditPDFPopGuideView.kHeight+80) viewFrame.origin.x += (areaBounds.size.width*0.5+KMEditPDFPopGuideView.kWidth*0.5) } guideWC.digitalBoxRect = viewFrame var beh = view.window?.collectionBehavior ?? [] beh.insert(.canJoinAllSpaces) guideWC.window?.collectionBehavior = beh guideWC.window?.setFrame(winFrame, display: false) guideWC.window?.minSize = winFrame.size guideWC.window?.maxSize = winFrame.size self._kAddchildwindow(guideWC.window!) guideWC.show() DispatchQueue.main.async { guideWC.interfaceThemeDidChanged(NSApp.appearance?.name ?? .aqua) } guideWC.settingCallback = { KMPreferenceController.shared.showWindow(nil) } } } } } // MARK: - Private Methods extension KMEditPDfHanddler { private func _kAddchildwindow(_ childW: NSWindow?) { guard let win = childW else { return } self.viewC?.view.window?.addChildWindow(win, ordered: .above) } private func _kRemoveChildWindow(_ childW: NSWindow?) { guard let win = childW else { return } let contains = self.viewC?.view.window?.childWindows?.contains(win) ?? false if contains { self.viewC?.view.window?.removeChildWindow(win) } } private func _addNotification() { NotificationCenter.default.addObserver(self, selector: #selector(_scrollViewDidScroll), name: NSScrollView.didLiveScrollNotification, object: self.listView?.documentView()) } private func _removeNotification() { NotificationCenter.default.removeObserver(self, name: NSScrollView.didLiveScrollNotification, object: self.listView?.documentView()) } @objc private func _scrollViewDidScroll(_ noti: Notification) { if let data = self.listView?.documentView().isEqual(to: noti.object), data { let win = KMEditPDFPopToolBarWindow.shared if win.isVisible == false { return } guard let area = (self.listView?.editingAreas().first as? CPDFEditArea) else { self.hiddenPopWindow() return } let areaBounds = (self.listView?.convert(area.bounds, from: area.page) as? NSRect) ?? .zero let winFrame = self.listView?.window?.frame ?? .zero let view: NSView? = nil var position = self.listView?.convert(areaBounds.origin, to: view) ?? .zero position.x += winFrame.origin.x position.y += winFrame.origin.y position.y += areaBounds.size.height position.y += 26 let wframe = NSMakeRect(position.x, position.y, win.frame.size.width, 44) win.setFrame(wframe, display: true) } } } // MARK: - Action extension KMEditPDfHanddler { func fontColorAction(color: NSColor?) { guard let theColor = color else { return } let editingAreas = self.editingAreas for area in editingAreas { if let data = area as? CPDFEditTextArea { self.listView?.setEditingSelectionFontColor(theColor, with: data) } } } func fontStyleAction(fontName: String?) { guard let font = CPDFFont.mappingFont(withFontString: fontName) else { return } let editingAreas = self.editingAreas for area in editingAreas { if let data = area as? CPDFEditTextArea { self.listView?.setEditSelectionCFont(font, with: data) } } } func fontAddAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last else { return } if area.isTextArea() == false { return } if let fontSize = self.listView?.editingSelectionFontSize(with: area as! CPDFEditTextArea) { self.listView?.setEditingSelectionFontSize(fontSize+1, with: area as! CPDFEditTextArea, isAutoSize: false) } } func fontReduceAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last else { return } if area.isTextArea() == false { return } if let fontSize = self.listView?.editingSelectionFontSize(with: area as! CPDFEditTextArea) { self.listView?.setEditingSelectionFontSize(fontSize-1, with: area as! CPDFEditTextArea, isAutoSize: false) } } func fontBoldAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last else { return } if area.isTextArea() == false { return } self.listView?.setCurrentSelectionIsBold(true, with: area as! CPDFEditTextArea) } func fontItalicAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last else { return } if area.isTextArea() == false { return } self.listView?.setCurrentSelectionIsItalic(true, with: area as! CPDFEditTextArea) } func textAlignmentAction(align: NSTextAlignment) { let editingAreas = self.editingAreas for area in editingAreas { if let data = area as? CPDFEditTextArea { self.listView?.setCurrentSelectionAlignment(align, with: data) } } } func leftRotateAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last as? CPDFEditImageArea else { return } // if let ang = self.listView?.getRotateWith(area) { // self.listView?.rotate(with: area, rotate: ang-90) // } // FMTrackEventManager.defaultManager.trackEvent(event: "SubTbr_PageEdit", withProperties: ["SubTbr_Btn": "Btn_SubTbr_PageEdit_Rotate"]) self.listView?.rotate(with: area, rotate: -90) // var frame = area.bounds // frame.size.width += 100 // self.listView?.setBoundsEditArea(area, withBounds: frame) // 文档拖拽、tooltip、多选场景、暗黑场景 // if self.listView.editingAreas()!.count == 1 && (self.listView.editingAreas()!.first is CPDFEditImageArea) { // self.listView.selectImageAreas = self.listView.editingAreas()!.first as? CPDFEditImageArea // } // self.editImageView.image = self.listView.selectImageAreas.thumbnailImage // self.delegate?.editImagePropertyViewControllerDidChanged(controller: self, type: .rotate) } func rightRotateAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } guard let area = editingAreas.last as? CPDFEditImageArea else { return } self.listView?.rotate(with: area, rotate: 90) } func reverseXAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } for area in editingAreas { if let data = area as? CPDFEditImageArea { self.listView?.horizontalMirror(with: data) } } } func reverseYAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } for area in editingAreas { if let data = area as? CPDFEditImageArea { self.listView?.verticalMirror(with: data) } } } func cropAction() { self.listView?.isEditImage = true let editingAreas = self.editingAreas if editingAreas.isEmpty { return } for area in editingAreas { if let data = area as? CPDFEditImageArea { self.listView?.enterCrop(with: data) } } self.hiddenPopWindow() Task { @MainActor in self.showCropComfirmWindow() } } func replaceAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } let panel = NSOpenPanel() panel.allowsMultipleSelection = false panel.allowedFileTypes = ["png","jpg"] panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { let openPath = panel.url?.path for area in editingAreas { if let data = area as? CPDFEditImageArea { // self.listView?.replace(data, imagePath: openPath!) self.listView?.replace(data, imagePath: openPath!, rect: data.bounds) } } } } } func exportAction() { let editingAreas = self.editingAreas if editingAreas.isEmpty { return } var imagesAreas: [CPDFEditImageArea] = [] for area in editingAreas { if let data = area as? CPDFEditImageArea { imagesAreas.append(data) } } if imagesAreas.count == 1 { let panel = NSSavePanel() panel.nameFieldStringValue = "\(NSLocalizedString("Untitled", comment: "")).jpg" panel.isExtensionHidden = true let response = panel.runModal() if response == .OK { let url = panel.url if FileManager.default.fileExists(atPath: url!.path) { try?FileManager.default.removeItem(atPath: url!.path) } let result = self.listView?.extractImage(with: imagesAreas.first, toImagePath: url!.path) ?? false if result { NSWorkspace.shared.activateFileViewerSelecting([url!]) } } } else if imagesAreas.count > 1 { let panel = NSOpenPanel() panel.canChooseFiles = false panel.canChooseDirectories = true panel.canCreateDirectories = true panel.allowsMultipleSelection = false panel.beginSheetModal(for: NSApp.mainWindow!) { response in if response == .OK { let outputURL = panel.url let s = self.listView?.document?.documentURL.lastPathComponent let folderPath = (self.listView?.document?.documentURL.deletingPathExtension().lastPathComponent ?? "") + "_extract" var filePath = outputURL?.path.stringByAppendingPathComponent(folderPath) var i = 1 let testFilePath = filePath while FileManager.default.fileExists(atPath: filePath!) { filePath = testFilePath! + "\(i)" i = i + 1 } try? FileManager.default.createDirectory(atPath: filePath!, withIntermediateDirectories: false, attributes: nil) var saveURLs : [URL] = [] for j in 0 ... imagesAreas.count-1 { let documentFileName = self.listView?.document?.documentURL.deletingPathExtension().lastPathComponent ?? "" var outPath = filePath! outPath = outPath.stringByAppendingPathComponent(documentFileName) outPath = outPath + "page \(j+1)" outPath = outPath.stringByAppendingPathExtension("jpg") let result = self.listView?.extractImage(with: imagesAreas[j], toImagePath: outPath) ?? false if result { saveURLs.append(URL(fileURLWithPath: outPath)) } } NSWorkspace.shared.activateFileViewerSelecting(saveURLs) } } } } func alignmentAction(align: CPDFActiveAreasAlignType) { KMPrint("updateFormAearsAlignMangent") let stype = align let editingAreas = self.editingAreas if editingAreas.count >= 2 { var zeroRect = NSRect.null var highestRect = NSZeroRect var widthestRect = NSZeroRect let fristArea : CPDFEditArea = editingAreas.first as! CPDFEditArea var leftestRect = fristArea.bounds var rightestRect = fristArea.bounds var topestRect = fristArea.bounds var bottomestRect = fristArea.bounds var leftestArea : CPDFEditArea = fristArea var rightestArea : CPDFEditArea = fristArea var topestArea : CPDFEditArea = fristArea var bottomestArea : CPDFEditArea = fristArea var totalWidth = 0.0 var totalHeight = 0.0 for i in 0 ... editingAreas.count-1 { let area : CPDFEditArea = editingAreas[i] as! CPDFEditArea zeroRect = zeroRect.union(area.bounds) totalWidth = totalWidth + area.bounds.width totalHeight = totalHeight + area.bounds.height if area.bounds.height > highestRect.height { highestRect = area.bounds } if area.bounds.width > widthestRect.width { widthestRect = area.bounds } if leftestRect.minX > area.bounds.minX { leftestRect = area.bounds leftestArea = area } if area.bounds.maxX > rightestRect.maxX { rightestRect = area.bounds rightestArea = area } if area.bounds.maxY > topestRect.maxY { topestRect = area.bounds topestArea = area } if bottomestRect.minY > area.bounds.minY { bottomestRect = area.bounds bottomestArea = area } } var resultAreasArray: [Any] = [] var newBoundsArray: [String] = [] if stype == .Left { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.x = zeroRect.origin.x newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .Right { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.x = zeroRect.maxX - bounds.size.width newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .Top { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.y = zeroRect.maxY - bounds.size.height newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .Bottom { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.y = zeroRect.minY newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .Horizontally { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.y = highestRect.midY - bounds.height/2 newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .Vertical { for i in 0 ... editingAreas.count-1 { let areas = editingAreas[i] as! CPDFEditArea var bounds = areas.bounds bounds.origin.x = widthestRect.midX - bounds.width/2 newBoundsArray.append(NSStringFromRect(bounds)) } resultAreasArray = editingAreas } else if stype == .DisHorizontally { let middleGap = zeroRect.width - leftestRect.width - rightestRect.width let otherAreasTotalWidth = totalWidth - leftestRect.width - rightestRect.width let gap = (middleGap - otherAreasTotalWidth)/CGFloat(editingAreas.count - 1) var areasCopyArray : [CPDFEditArea] = editingAreas as! [CPDFEditArea] areasCopyArray.sorted(by: { obj1, obj2 in let area1 = obj1 let area2 = obj2 if area1.bounds.origin.x < area2.bounds.origin.x { return true } else { return false } }) if let index = areasCopyArray.firstIndex(of: leftestArea) { areasCopyArray.remove(at: index) } if let index = areasCopyArray.firstIndex(of: rightestArea) { areasCopyArray.remove(at: index) } var leftStartX = leftestRect.maxX + gap for i in 0 ... areasCopyArray.count-1 { let areas = areasCopyArray[i] var bounds = areas.bounds bounds.origin.x = leftStartX newBoundsArray.append(NSStringFromRect(bounds)) leftStartX = leftStartX + bounds.width + gap } resultAreasArray = areasCopyArray } else if stype == .DisVertical { let middleGap = zeroRect.height - topestRect.height - bottomestRect.height let otherAreasTotalHeight = totalHeight - topestRect.height - bottomestRect.height let gap = (middleGap - otherAreasTotalHeight)/CGFloat(editingAreas.count - 1) var areasCopyArray : [CPDFEditArea] = editingAreas as! [CPDFEditArea] areasCopyArray.sorted(by: { obj1, obj2 in let area1 = obj1 let area2 = obj2 if area1.bounds.origin.x < area2.bounds.origin.x { return true } else { return false } }) if let index = areasCopyArray.firstIndex(of: topestArea) { areasCopyArray.remove(at: index) } if let index = areasCopyArray.firstIndex(of: bottomestArea) { areasCopyArray.remove(at: index) } var bottomStartY = bottomestRect.maxY + gap for i in 0 ... areasCopyArray.count-1 { let areas = areasCopyArray[i] var bounds = areas.bounds bounds.origin.y = bottomStartY newBoundsArray.append(NSStringFromRect(bounds)) bottomStartY = bottomStartY + bounds.height + gap } resultAreasArray = areasCopyArray } var oldBounds : [String] = [] for i in 0 ... resultAreasArray.count-1 { let area : CPDFEditArea = resultAreasArray[i] as! CPDFEditArea oldBounds.append(NSStringFromRect(area.bounds)) self.listView?.setBoundsEditArea(area, withBounds: NSRectFromString(newBoundsArray[i])) } self.listView?.setNeedsDisplayForVisiblePages() } } } // MARK: - CPDFViewDelegate extension KMEditPDfHanddler: CPDFViewDelegate { // 编辑区块已经改变 func pdfViewEditingAreaDidChanged(_ pdfView: CPDFView!) { let isEdited = self.listView?.isEdited() ?? false if isEdited { // 记录编辑状态 self.viewC?.recordIsPDFDocumentEdited(type: .editText) } if annotationType != .addText { NotificationCenter.default.post(name: NSNotification.Name(rawValue: "kPDFViewEditingAreaDidChanged"), object: self.listView?.document) } let areas = self.listView?.editingAreas() as? [CPDFEditArea] ?? [] if areas.isEmpty { self.hiddenPopWindow() let toolMode = self.listView?.toolMode ?? .none let annotationType = self.annotationType if toolMode == .editPDFToolMode { if annotationType == .addImage || annotationType == .addText { if self.isEditImage { self.viewC?.menuItemEditingClick_CropImage(sender: NSMenuItem()) } else { // if self.listView.annotationType == .addImage { // self.closeRightPane() // } if annotationType == .addImage { if self.rightViewC?.eidtPDFImageProperty != nil { self.rightViewC?.eidtPDFImageProperty.reloadData() } } // self.openRightPane() } } else { // self.viewC?.closeRightPane() self.rightViewC?.isHidden = true } } else { self.rightViewC?.isHidden = true self.viewC?.closeRightPane() if self.subViewType == .EditPDFAddText && annotationType == .addText { self.rightViewC?.eidtPDFTextProperty.initData() } } return } self.viewC?.model.isPDFTextImageEdited = true let subViewType = self.rightViewC?.subViewType ?? .None if self.annotationType == .addImage { var isImageArea = false for i in 0 ..< areas.count { if areas[i] is CPDFEditImageArea { isImageArea = true } } if isImageArea { self.rightViewC?.isHidden = false if self.subViewType == .EditPDFAddImage { self.rightViewC?.subViewType = .EditPDFAddImage self.rightViewC?.eidtPDFImageProperty.reloadData() } self.openRightPane() } else { self.rightViewC?.isHidden = true // self.viewC?.closeRightPane() } } else if self.subViewType == .EditPDFAddText && annotationType == .addText { self.rightViewC?.isHidden = false let count = self.listView?.editingSelectionString()?.count ?? 0 if count != 0 { self.rightViewC?.eidtPDFTextProperty.reloadData() } else { self.rightViewC?.eidtPDFTextProperty.refreshSelectAreaProperty(needDefaultData: true) } self.openRightPane() } else { var textsAreas : [CPDFEditTextArea] = [] var imagesAreas : [CPDFEditImageArea] = [] let count = self.listView?.editingAreas()?.count ?? 0 if count < 1 { return } for i in 0 ..< areas.count { if areas[i] is CPDFEditTextArea { textsAreas.append(areas[i] as! CPDFEditTextArea) } if areas[i] is CPDFEditImageArea { imagesAreas.append(areas[i] as! CPDFEditImageArea) } } if textsAreas.count > 0 && textsAreas.count == areas.count { self.rightViewC?.isHidden = false self.rightViewC?.subViewType = .EditPDFAddText self.rightViewC?.eidtPDFTextProperty?.reloadData() self.openRightPane() } else if imagesAreas.count > 0 { self.rightViewC?.isHidden = false self.rightViewC?.subViewType = .EditPDFAddImage self.rightViewC?.eidtPDFImageProperty?.reloadData() self.openRightPane() } } var flag: CPDFEditArea? for area in areas { if flag == nil { flag = area continue } if let data = flag, data.bounds.maxY < area.bounds.maxY { flag = area } } if let data = flag { self.showPopWindow(positionRect: data.bounds) } } func pdfViewEditingCropBoundsDidChanged(_ pdfView: CPDFView!, editing editArea: CPDFEditArea!) { if editArea != nil && (editArea is CPDFEditImageArea){ self.listView?.cropAreas = editArea as? CPDFEditImageArea } } func pdfViewEditingAddImageArea(_ pdfView: CPDFView!, add page: CPDFPage!, add rect: CGRect) { if self.isEditImage { self.viewC?.menuItemEditingClick_CropImage(sender: NSMenuItem()) } else { 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 var 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 } let scale = min(previewSize.width / imageSize.width, previewSize.height / 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()) self.viewC?.model.isPDFTextImageEdited = true self.viewC?.recordIsPDFDocumentEdited(type: .editImage) self.showPopWindow(positionRect: imageRect) } } } } } } func pdfViewEditingAddTextArea(_ pdfView: CPDFView!, add page: CPDFPage!, add rect: CGRect) { let window = KMEditPDFPopToolBarWindow.shared if (window.isVisible) { self.hiddenPopWindow() let areas = self.listView?.editingAreas() as? [CPDFEditArea] ?? [] if let area = areas.last { if let data = area as? CPDFEditTextArea { if let str = data.editTextAreaString(), str.isEmpty { self.listView?.remove(with: [area]) } } } return } var newRect = rect if CGSizeEqualToSize(rect.size, .zero) { newRect = CGRect(x: rect.origin.x, y: rect.origin.y - 12, width: 20, height: 12) } else { newRect = CGRect(x: rect.origin.x, y: rect.origin.y + rect.size.height - 12, width: rect.size.width, height: 12) } let model = KMEditPDFTextManager.manager.fetchUserDefaultData(type: .commonly) let fontName = KMEditPDFTextManager.manager.fetchFontName(fontName: model.fontName) let fontSize = model.fontSize let fontColor = model.color let fontAlign = model.alignment let fontStyle = KMEditPDFTextManager.manager.fetchFontStyle(fontName: model.fontName) NSColorPanel.shared.color = fontColor let font = KMEditPDFTextManager.manager.fetchFont(fontName: fontName, style: fontStyle, size: fontSize) let attri = CEditAttributes() attri.font = font attri.fontColor = fontColor attri.alignment = fontAlign self.listView?.createStringBounds(newRect, with: attri, page: page) // self.rightViewC != nil && if self.subViewType == .EditPDFAddText && self.annotationType == .addText { self.rightViewC?.eidtPDFTextProperty.refreshSelectAreaProperty(needDefaultData: true) } self.showPopWindow(positionRect: newRect) } // 文本区块 选中文本已经变化 func pdfViewEditingSelectionDidChanged(_ pdfView: CPDFView!) { // self.viewC?.rightSideViewController != nil && if self.subViewType == .EditPDFAddText { self.rightViewC?.eidtPDFTextProperty.reloadData() self.rightViewC?.eidtPDFTextProperty.updateTextTextPresuppositionState() } } func pdfViewMobileEditingBegan(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { self.hiddenPopWindow() } func pdfViewMobileEditingMove(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { } func pdfViewMobileEditingEnd(_ point: CGPoint, for pdfView: CPDFView!, forEditing editingAreas: [CPDFEditArea]!) { self.showPopWindow(positionRect: .zero) } }