// // KMMeasureSideVC.swift // Cisdem PDFMaster // // Created by wanjun on 2024/7/15. // import Cocoa private enum KMMeasureType: Int { case line = 0 case multilines case polygon case rectangle } @objcMembers class KMMeasureSideVC: NSViewController { // Preview @IBOutlet private weak var previewImageBox: NSBox! @IBOutlet private weak var previewImageView: NSImageView! // Type @IBOutlet private weak var typeView: NSView! @IBOutlet private weak var typeSubView1: NSView! @IBOutlet private weak var typeButton1: NSButton! @IBOutlet private weak var typeSubView2: NSView! @IBOutlet private weak var typeButton2: NSButton! @IBOutlet private weak var typeSubView3: NSView! @IBOutlet private weak var typeButton3: NSButton! @IBOutlet private weak var typeSubView4: NSView! @IBOutlet private weak var typeButton4: NSButton! @IBOutlet private weak var verticalLine1: NSBox! @IBOutlet private weak var verticalLine2: NSBox! @IBOutlet private weak var verticalLine3: NSBox! @IBOutlet private weak var type_TopConstant: NSLayoutConstraint! // Border & Fill Color @IBOutlet private weak var border_FillView: NSView! @IBOutlet private weak var border_Label: NSTextField! @IBOutlet private weak var borderColor_View: NSView! @IBOutlet private weak var borderColor_Button: NSButton! @IBOutlet private weak var borderColor_TopConstant: NSLayoutConstraint! // Line Color @IBOutlet private weak var lineColor_View: NSView! @IBOutlet private weak var lineColor_Label: NSTextField! @IBOutlet private weak var lineColor_ColorView: NSView! @IBOutlet private weak var lineColor_ColorButton: NSButton! @IBOutlet private weak var lineColor_TopConstant: NSLayoutConstraint! // Opacity @IBOutlet private weak var opacity_View: NSView! @IBOutlet private weak var opacity_Label: NSTextField! @IBOutlet private weak var opacity_Slider: NSSlider! @IBOutlet private weak var opacity_ComboBox: KMComboBox! @IBOutlet private weak var opacity_TopConstant: NSLayoutConstraint! // Thickness @IBOutlet private weak var thickness_View: NSView! @IBOutlet private weak var thickness_Label: NSTextField! @IBOutlet private weak var thickness_Slider: NSSlider! @IBOutlet private weak var thickness_ComboBox: KMComboBox! @IBOutlet private weak var thickness_TopConstant: NSLayoutConstraint! // Line Style @IBOutlet private weak var lineStyle_View: NSView! @IBOutlet private weak var lineStyle_Label: NSTextField! @IBOutlet private weak var lineStyle_SolidButton: NSButton! @IBOutlet private weak var lineStyle_SolidImageView: NSImageView! @IBOutlet private weak var lineStyle_DottedButton: NSButton! @IBOutlet private weak var lineStyle_DottedImageView: NSImageView! @IBOutlet private weak var lineStyle_TextField: NSTextField! @IBOutlet private weak var lineStyle_TopConstant: NSLayoutConstraint! // Start & End @IBOutlet private weak var startEnd_View: NSView! @IBOutlet private weak var startEnd_Label: NSTextField! @IBOutlet private weak var startEnd_StartPopUpButton: KMPopUpButton! @IBOutlet private weak var startEnd_EndPopUpButton: KMPopUpButton! @IBOutlet private weak var startEnd_TopConstant: NSLayoutConstraint! // Font @IBOutlet private weak var font_View: NSView! @IBOutlet private weak var font_Label: NSTextField! @IBOutlet private weak var font_PopUpButton: KMPopUpButton! @IBOutlet private weak var font_ColorView: NSView! @IBOutlet private weak var font_ColorButton: NSButton! @IBOutlet private weak var font_StylePopUpButton: KMPopUpButton! @IBOutlet private weak var font_SizeComboBox: KMComboBox! @IBOutlet private weak var font_TopConstant: NSLayoutConstraint! var annotation: CPDFAnnotation? weak var pdfView: CPDFListView? var _annotationModel: CPDFAnnotationModel? var _annotations: [Any] = [] private var measureType: KMMeasureType = .line deinit { NotificationCenter.default.removeObserver(self) } override func viewDidLoad() { super.viewDidLoad() // Do view setup here. if annotationType == .line { if pdfView?.toolMode == .measureToolMode { measureType = .line } } else if annotationType == .square { if pdfView?.toolMode == .measureToolMode { measureType = .rectangle } } else if annotationType == .polyGon { measureType = .polygon } else if annotationType == .polyLine { measureType = .multilines } languageLocalization() uiInitialize() layoutConstraintRefresh() NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidEndEditingNotification(_:)), name: NSControl.textDidEndEditingNotification, object: lineStyle_TextField) } // MARK: Privately Methods private func languageLocalization() -> Void { if measureType == .polygon { border_Label.stringValue = NSLocalizedString("Fill", comment: "") } else { border_Label.stringValue = NSLocalizedString("Border", comment: "") } lineColor_Label.stringValue = NSLocalizedString("Line Color", comment: "") opacity_Label.stringValue = NSLocalizedString("Opacity", comment: "") thickness_Label.stringValue = NSLocalizedString("Thickness", comment: "") lineStyle_Label.stringValue = NSLocalizedString("Line Style", comment: "") startEnd_Label.stringValue = NSLocalizedString("Start & End", comment: "") font_Label.stringValue = NSLocalizedString("Font", comment: "") } private func uiInitialize() -> Void { border_Label.textColor = KMAppearance.Layout.h0Color() border_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) lineColor_Label.textColor = KMAppearance.Layout.h0Color() lineColor_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) opacity_Label.textColor = KMAppearance.Layout.h0Color() opacity_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) thickness_Label.textColor = KMAppearance.Layout.h0Color() thickness_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) lineStyle_Label.textColor = KMAppearance.Layout.h0Color() lineStyle_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) startEnd_Label.textColor = KMAppearance.Layout.h0Color() startEnd_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) font_Label.textColor = KMAppearance.Layout.h0Color() font_Label.font = NSFont(descriptor: NSFontDescriptor(name: "Segoe UI", size: 14.0).withSymbolicTraits(.bold), size: 14.0) ?? NSFont(name: "Segoe UI", size: 14.0) opacity_ComboBox.type = .none opacity_ComboBox.comboxRect = opacity_ComboBox.bounds thickness_ComboBox.type = .none thickness_ComboBox.comboxRect = thickness_ComboBox.bounds font_PopUpButton.type = .arrowDown font_PopUpButton.removeAllItems() font_PopUpButton.type = .arrowDown font_PopUpButton.removeAllItems() font_SizeComboBox.type = .none lineStyle_SolidImageView.image = NSImage(named: "KMImageNameLifeStyle") lineStyle_DottedImageView.image = NSImage(named: "KMImageNameLifeStyle2") lineStyle_TextField.isEnabled = false if annotationModel.dashPattern().count > 0 { lineStyle_TextField.stringValue = (annotationModel.dashPattern().first as! NSNumber).description } else { lineStyle_TextField.stringValue = "5" } annotationFontReload() if measureType == .line { previewImageView.image = NSImage(named: "ImageNameToolbarMeasureLine") startEnd_StartPopUpButton.type = .arrowDown startEnd_StartPopUpButton.removeAllItems() startEnd_EndPopUpButton.type = .arrowDown startEnd_EndPopUpButton.removeAllItems() let startMenu = NSMenu() _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 0) _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 1) _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 2) _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 3) _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 4) _ = startMenu.addItem(withTitle: "", action: #selector(startMenuItemAction(_:)), target: self, tag: 5) startEnd_StartPopUpButton.menu = startMenu let endMenu = NSMenu() _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 0) _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 1) _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 2) _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 3) _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 4) _ = endMenu.addItem(withTitle: "", action: #selector(endMenuItemAction(_:)), target: self, tag: 5) startEnd_EndPopUpButton.menu = endMenu let startPopMenu = startEnd_StartPopUpButton.menu let endPopMenu = startEnd_EndPopUpButton.menu let startLineStyle = annotationModel.startLineStyle() let endLineStyle = annotationModel.endLineStyle() let startArr = self.startLineStyle() let endArr = self.endLineStyle() for i in 0.. Void { verticalLine1.isHidden = false verticalLine2.isHidden = false verticalLine3.isHidden = false typeSubView1.backgroundColor(.clear) typeSubView2.backgroundColor(.clear) typeSubView3.backgroundColor(.clear) typeSubView4.backgroundColor(.clear) typeButton1.image = NSImage(named: "ImageNameToolbarMeasureLine") typeButton2.image = NSImage(named: "ImageNameToolbarPolyline") typeButton3.image = NSImage(named: "ImageNameToolbarPolygon") typeButton4.image = NSImage(named: "ImageNameToolbarMeasureSquare") typeButton1.isEnabled = false typeButton2.isEnabled = false typeButton3.isEnabled = false typeButton4.isEnabled = false if measureType == .line { verticalLine1.isHidden = true typeSubView1.backgroundColor(NSColor.km_init(hex: "#477EDE", alpha: 0.1)) typeButton1.isEnabled = true } else if measureType == .multilines { verticalLine1.isHidden = true verticalLine2.isHidden = true typeSubView2.backgroundColor(NSColor.km_init(hex: "#477EDE", alpha: 0.1)) typeButton2.isEnabled = true } else if measureType == .polygon { verticalLine2.isHidden = true verticalLine3.isHidden = true typeSubView3.backgroundColor(NSColor.km_init(hex: "#477EDE", alpha: 0.1)) typeButton3.isEnabled = false } else if measureType == .rectangle { verticalLine3.isHidden = true typeSubView4.backgroundColor(NSColor.km_init(hex: "#477EDE", alpha: 0.1)) } } private func borderColorViewRefresh() -> Void { if measureType == .polygon || measureType == .rectangle { if annotation is CPDFPolygonAnnotation { let newAnnotation = (annotation as! CPDFPolygonAnnotation) borderColor_View.backgroundColor(newAnnotation.interiorColor) } } else { borderColor_View.backgroundColor(annotationModel.color()) } } private func lineColorViewRefresh() -> Void { lineColor_ColorView.backgroundColor(annotationModel.color()) } private func fontColorViewRefresh() -> Void { font_ColorView.backgroundColor(annotationModel.fontColor()) } private func opacityViewRefresh() -> Void { opacity_Slider.floatValue = Float(annotationModel.opacity()) opacity_Slider.toolTip = "\(Int(Float(annotationModel.opacity()) * 100))%" opacity_ComboBox.stringValue = "\(Int(Float(annotationModel.opacity()) * 100))%" } private func thicknessViewRefresh() -> Void { thickness_Slider.floatValue = Float(annotationModel.lineWidth()) thickness_Slider.toolTip = "\(Int(Float(annotationModel.lineWidth())))" thickness_ComboBox.stringValue = "\(Int(Float(annotationModel.lineWidth())))" } private func lineStyleViewRefresh() -> Void { if annotationModel.style() == .solid { lineStyle_SolidButton.image = NSImage(named: "KMImageNameCheckboxRadiSel") lineStyle_DottedButton.image = NSImage(named: "KMImageNameCheckboxRadi") lineStyle_TextField.isEnabled = false } else { lineStyle_SolidButton.image = NSImage(named: "KMImageNameCheckboxRadi") lineStyle_DottedButton.image = NSImage(named: "KMImageNameCheckboxRadiSel") lineStyle_TextField.isEnabled = true } } private func layoutConstraintRefresh() -> Void { border_FillView.isHidden = false lineColor_View.isHidden = false opacity_View.isHidden = false thickness_View.isHidden = false lineStyle_View.isHidden = false startEnd_View.isHidden = false font_View.isHidden = false if measureType == .line { lineColor_View.isHidden = true } else if measureType == .multilines { lineColor_View.isHidden = true startEnd_View.isHidden = true } else if measureType == .polygon { startEnd_View.isHidden = true } else if measureType == .rectangle { thickness_View.isHidden = true startEnd_View.isHidden = true } borderColor_TopConstant.constant = !border_FillView.isHidden ? 10.0 : -CGRectGetHeight(border_FillView.bounds) lineColor_TopConstant.constant = !lineColor_View.isHidden ? 0.0 : -CGRectGetHeight(lineColor_View.bounds) opacity_TopConstant.constant = !opacity_View.isHidden ? 0.0 : -CGRectGetHeight(opacity_View.bounds) thickness_TopConstant.constant = !thickness_View.isHidden ? 0.0 : -CGRectGetHeight(thickness_View.bounds) lineStyle_TopConstant.constant = !lineStyle_View.isHidden ? 0.0 : -CGRectGetHeight(lineStyle_View.bounds) startEnd_TopConstant.constant = !startEnd_View.isHidden ? 0.0 : -CGRectGetHeight(startEnd_View.bounds) font_TopConstant.constant = !font_View.isHidden ? 0.0 : -CGRectGetHeight(font_View.bounds) } private func setFontStyle(fontName: String, currentStyle style: String?) -> UInt { var selectIndex: UInt = 0 let menu = NSMenu() let fontStyleNames = CPDFFont.fontNames(forFamilyName: fontName) for i in 0.. [NSImage] { let size = NSSize(width: 109.0, height: 12.0) let image1 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image2 = NSImage.image(with: size) { dstRect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 12.0, y: 6.0)) path.appendRect(NSRect(x: 6.0, y: 3.0, width: 6.0, height: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image3 = NSImage.image(with: size) { dstRect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 12.0, y: 6.0)) path.appendOval(in: NSRect(x: 6.0, y: 3.0, width: 6.0, height: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image4 = NSImage.image(with: size) { dstRect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 14.0, y: 6.0)) path.move(to: NSPoint(x: 14.0, y: 6.0)) path.line(to: NSPoint(x: 10.0, y: 10.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 10.0, y: 2.0)) path.close() path.lineWidth = 2.0 path.stroke() return true } let image5 = NSImage.image(with: size) { dstRect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.move(to: NSPoint(x: 15.0, y: 3.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 15.0, y: 9.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image6 = NSImage.image(with: size) { dstRect in let path = NSBezierPath() path.move(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.move(to: NSPoint(x: 15.0, y: 3.0)) path.line(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 15.0, y: 9.0)) path.close() path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } return [image1, image5, image6, image2, image3, image4] } private func endLineStyle() -> [NSImage] { let size = NSSize(width: 109.0, height: 12.0) let image1 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 93.0, y: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image2 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 87.0, y: 6.0)) path.appendRect(NSRect(x: 87.0, y: 3.0, width: 6.0, height: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image3 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 87.0, y: 6.0)) path.appendOval(in: NSRect(x: 87.0, y: 3.0, width: 6.0, height: 6.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image4 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 87.0, y: 6.0)) path.move(to: NSPoint(x: 87.0, y: 6.0)) path.line(to: NSPoint(x: 91.0, y: 10.0)) path.line(to: NSPoint(x: 95.0, y: 6.0)) path.line(to: NSPoint(x: 91.0, y: 2.0)) path.close() path.lineWidth = 2.0 path.stroke() return true } let image5 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 93.0, y: 6.0)) path.move(to: NSPoint(x: 84.0, y: 3.0)) path.line(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 84.0, y: 9.0)) path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } let image6 = NSImage.image(with: size) { rect in let path = NSBezierPath() path.move(to: NSPoint(x: 6.0, y: 6.0)) path.line(to: NSPoint(x: 93.0, y: 6.0)) path.move(to: NSPoint(x: 84.0, y: 3.0)) path.line(to: NSPoint(x: 93.0, y: 6.0)) path.line(to: NSPoint(x: 84.0, y: 9.0)) path.close() path.lineWidth = 2.0 NSColor.black.setStroke() path.stroke() return true } return [image1, image5, image6, image2, image3, image4] } private func isNumericUsingNSRegularExpression(_ input: String) -> Bool { let pattern = "^[0-9]+$" do { let regex = try NSRegularExpression(pattern: pattern) let matches = regex.matches(in: input, range: NSRange(location: 0, length: input.utf16.count)) return matches.count > 0 } catch { print("Invalid regex pattern") return false } } // MARK: Publicly Methods // MARK: Action @IBAction func typeButtonAction(_ sender: NSButton) { } @IBAction func customColorAction(_ sender: NSButton) { NSColorPanel.shared.setAction(nil) NSColorPanel.shared.setTarget(nil) NSColorPanel.shared.setTarget(self) NSColorPanel.shared.showsAlpha = true if sender.tag == 0 { NSColorPanel.shared.setAction(#selector(colorPanelAction1(_:))) } else if sender.tag == 1 { NSColorPanel.shared.setAction(#selector(colorPanelAction2(_:))) } else if sender.tag == 2 { NSColorPanel.shared.setAction(#selector(colorPanelAction3(_:))) } NSColorPanel.shared.orderFront(nil) } @IBAction func opacitySliderAction(_ sender: Any) { var opcity = CGFloat(opacity_Slider.floatValue) if opcity == 0 { opcity = 0.0001 } annotationModel.setOpacity(opcity) opacityViewRefresh() updateAnnotation() } @IBAction func opacityComboBoxAction(_ sender: Any) { opacity_Slider.floatValue = Float(opacity_ComboBox.floatValue / 100) var opcity = CGFloat(opacity_Slider.floatValue) if opcity == 0 { opcity = 0.0001 } annotationModel.setOpacity(opcity) opacityViewRefresh() updateAnnotation() } @IBAction func thicknessSliderAction(_ sender: Any) { let thickness = CGFloat(thickness_Slider.floatValue) annotationModel.setLineWidth(thickness) thicknessViewRefresh() updateAnnotation() } @IBAction func thicknessComboBoxAction(_ sender: Any) { thickness_Slider.floatValue = Float(thickness_ComboBox.floatValue) let thickness = CGFloat(thickness_Slider.floatValue) annotationModel.setLineWidth(thickness) thicknessViewRefresh() updateAnnotation() } @IBAction func lineStyleButtonAction(_ sender: NSButton) { if sender.tag == 0 { annotationModel.setStyle(.solid) } else { annotationModel.setStyle(.dashed) annotation?.setDashPattern(annotationModel.dashPattern()) } lineStyleViewRefresh() updateAnnotation() } @IBAction func startMenuItemAction(_ sender: NSMenuItem) { let startType: CPDFLineStyle = (CPDFLineStyle(rawValue: sender.tag) ?? CPDFLineStyle(rawValue: 0))! annotationModel.setStart(startType) updateAnnotation() } @IBAction func endMenuItemAction(_ sender: NSMenuItem) { let endType: CPDFLineStyle = (CPDFLineStyle(rawValue: sender.tag) ?? CPDFLineStyle(rawValue: 0))! annotationModel.setEnd(endType) updateAnnotation() } @IBAction func fontPopUpButtonAction(_ sender: NSPopUpButton) { guard let selectedItem = font_PopUpButton.selectedItem else { return } let resultAtt = NSMutableAttributedString(attributedString: selectedItem.attributedTitle!) let familyString = resultAtt.string let selectIndex = setFontStyle(fontName: familyString, currentStyle: nil) guard let styleString = font_StylePopUpButton.selectedItem?.title else { return } font_StylePopUpButton.selectItem(at: Int(selectIndex)) for tAnnotation in annotations { if tAnnotation is CPDFLineAnnotation { let newAnnotation = (tAnnotation as! CPDFLineAnnotation) newAnnotation.cFont = CPDFFont(familyName: familyString, fontStyle: styleString) } else if tAnnotation is CPDFPolygonAnnotation { let newAnnotation = (tAnnotation as! CPDFPolygonAnnotation) newAnnotation.cFont = CPDFFont(familyName: familyString, fontStyle: styleString) } else if tAnnotation is CPDFPolylineAnnotation { let newAnnotation = (tAnnotation as! CPDFPolylineAnnotation) newAnnotation.cFont = CPDFFont(familyName: familyString, fontStyle: styleString) } } pdfView?.setNeedsDisplay(annotation) } @IBAction func fontSizeComboBoxAction(_ sender: NSComboBox) { if annotationModel.annotations != nil { for tAnnotation in annotations { if tAnnotation is CPDFLineAnnotation { let newAnnotation = (tAnnotation as! CPDFLineAnnotation) newAnnotation.fontSize = CGFloat(font_SizeComboBox.floatValue) } else if tAnnotation is CPDFPolygonAnnotation { let newAnnotation = (tAnnotation as! CPDFPolygonAnnotation) newAnnotation.fontSize = CGFloat(font_SizeComboBox.floatValue) } else if tAnnotation is CPDFPolylineAnnotation { let newAnnotation = (tAnnotation as! CPDFPolylineAnnotation) newAnnotation.fontSize = CGFloat(font_SizeComboBox.floatValue) } } } else { if annotationType == .line || annotationType == .polyGon || annotationType == .polyLine { if let data = annotationModel.fontName() { let font = NSFont(name: data, size: annotationModel.fontSize()) ?? NSFont.systemFont(ofSize: 16) let newFont = NSFont(name: font.fontName, size: CGFloat(font_SizeComboBox.floatValue)) if let newFont = newFont { annotationModel.setFontName(newFont.fontName) annotationModel.setFontSize(newFont.pointSize) } } } } updateAnnotation() } //字重 NSFontWeight @IBAction func fontStylePopUpButtonAction(_ sender: NSPopUpButton) { if let styleString = font_StylePopUpButton.selectedItem?.title { if annotationModel.annotations != nil { for tAnnotation in self.annotations { if tAnnotation is CPDFLineAnnotation { let newAnnotation = (tAnnotation as! CPDFLineAnnotation) newAnnotation.cFont = CPDFFont(familyName: newAnnotation.cFont.familyName, fontStyle: styleString) } else if tAnnotation is CPDFPolygonAnnotation { let newAnnotation = (tAnnotation as! CPDFPolygonAnnotation) newAnnotation.cFont = CPDFFont(familyName: newAnnotation.cFont.familyName, fontStyle: styleString) } else if tAnnotation is CPDFPolylineAnnotation { let newAnnotation = (tAnnotation as! CPDFPolylineAnnotation) newAnnotation.cFont = CPDFFont(familyName: newAnnotation.cFont.familyName, fontStyle: styleString) } } } else { if annotationType == .line || annotationType == .polyGon || annotationType == .polyLine { if let data = annotationModel.fontName() { let font = NSFont(name: data, size: annotationModel.fontSize()) ?? NSFont.systemFont(ofSize: 16) if let fontSize = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.size) as? Int, let familyString = font.fontDescriptor.object(forKey: NSFontDescriptor.AttributeName.family) as? String { let attributeFontDescriptor = NSFontDescriptor(fontAttributes: [NSFontDescriptor.AttributeName.family: familyString, NSFontDescriptor.AttributeName.face: styleString]) if let newFont = NSFont(descriptor: attributeFontDescriptor, size: CGFloat(fontSize)) { annotationModel.setFontName(newFont.fontName) annotationModel.setFontSize(newFont.pointSize) } } } } } } updateAnnotation() } // MARK: Set & Get var annotations: [Any] { set { _annotations = newValue self.annotation = (newValue.first as? CPDFAnnotation) } get { return _annotations } } var annotationModel: CPDFAnnotationModel { get { return _annotationModel! } set { _annotationModel = newValue if _annotationModel?.annotations != nil { if annotationModel.annotations.count > 0 { annotations = _annotationModel?.annotations as! [CPDFAnnotation] } } } } var annotationType: CAnnotationType { get { if let ann = annotation?.isKind(of: CPDFLineAnnotation.self), ann { if (annotation as! CPDFLineAnnotation).isMeasure { return .line } } else if let ann = annotation?.isKind(of: CPDFPolygonAnnotation.self), ann { if pdfView?.annotationType == .square { return .square } return .polyGon } else if let ann = annotation?.isKind(of: CPDFPolylineAnnotation.self), ann { return .polyLine } return .unkown } } // MARK: Notification @objc func textFieldDidEndEditingNotification(_ notification: Notification) { if lineStyle_TextField.stringValue.isEmpty == true { return } if isNumericUsingNSRegularExpression(lineStyle_TextField.stringValue) == false { lineStyle_TextField.stringValue = "5" return } var dashFloat = Float(lineStyle_TextField.stringValue) if dashFloat == 0 { lineStyle_TextField.stringValue = "1" dashFloat = 1.0 } let number = NSNumber(value: dashFloat!) var lineDashPattern: [Any] = annotationModel.dashPattern() let array: [NSNumber] if annotationModel.dashPattern() is [NSNumber] { if lineDashPattern.isEmpty { array = [number] } else { lineDashPattern[0] = number array = lineDashPattern as! [NSNumber] } } else { array = [number] } annotation?.setDashPattern(array) updateAnnotation() } }