import Cocoa private let kKMSignayureTextMaxFontSize: CGFloat = 28.0 private let kKMSignayureTextMaxWidth: CGFloat = 300 private let kKMSignayureTextEdgeOffset: CGFloat = 5 @objcMembers class KMVerticallyCenteredSecureTextFieldCell: NSTextFieldCell { func adjustedFrame(toVerticallyCenterText rect: NSRect) -> NSRect { let offset = floor((rect.size.height / 2 - (font!.ascender))) return rect.insetBy(dx: 0.0, dy: offset) } override func edit(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate delegateObj: Any?, event: NSEvent?) { super.edit(withFrame: adjustedFrame(toVerticallyCenterText: rect), in: controlView, editor: textObj, delegate: delegateObj, event: event) } override func select(withFrame rect: NSRect, in controlView: NSView, editor textObj: NSText, delegate delegateObj: Any?, start selStart: Int, length selLength: Int) { super.select(withFrame: adjustedFrame(toVerticallyCenterText: rect), in: controlView, editor: textObj, delegate: delegateObj, start: selStart, length: selLength) } override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) { super.drawInterior(withFrame: adjustedFrame(toVerticallyCenterText: cellFrame), in: controlView) } } @objcMembers class KMSignayureTextField: NSTextField { var originalTextColor: NSColor? override func addSubview(_ view: NSView) { super.addSubview(view) if let view1 = view.subviews.first as? NSTextView { let textview = view1 textview.insertionPointColor = NSColor(red: 102.0 / 255.0, green: 102.0 / 255.0, blue: 102.0 / 255.0, alpha: 1.0) } } } @objc protocol KMChangeSignatureTextDelegate: NSObjectProtocol { func changeSignatureText(_ isTrue: Bool) } @objcMembers class KMPDFSignatureTextView: NSView, NSTextFieldDelegate { @IBOutlet var nameTextFiled: KMSignayureTextField! @IBOutlet var labelWidthLayoutConstraint: NSLayoutConstraint! @IBOutlet var verticalLineBox: NSBox! var keyboardColor: NSColor = NSColor(red: 0, green: 0, blue: 0, alpha: 1) { didSet { self.nameTextFiled.textColor = keyboardColor } } var fontName: String = "" { didSet { var fontSize: CGFloat = 14.0 if !self.nameTextFiled.stringValue.isEmpty { fontSize = kKMSignayureTextMaxFontSize } if let maxFont = NSFont(name: fontName, size: fontSize) { let size = sizeOfString(self.nameTextFiled.stringValue, withFontSize: maxFont) var width = size.width + kKMSignayureTextEdgeOffset * 2 var scale: CGFloat = 1.0 scale = min(kKMSignayureTextMaxWidth / width, 60.0 / (size.height + 2)) if width >= 100 { self.labelWidthLayoutConstraint.constant = width } if let font = NSFont(name: fontName, size: fontSize) { self.nameTextFiled.font = font } let isTrue = !self.nameTextFiled.stringValue.isEmpty if let callback = self.changeSignatureTextCallback { callback(isTrue) } if let delegate = self.delegate { delegate.changeSignatureText(isTrue) } } } } var changeSignatureTextCallback: ((Bool) -> Void)? weak var delegate: KMChangeSignatureTextDelegate? override func awakeFromNib() { super.awakeFromNib() self.nameTextFiled.placeholderString = NSLocalizedString("Sign Here", comment: "") self.nameTextFiled.font = NSFont.systemFont(ofSize: 14.0) // self.verticalLineBox.fillColor = NSColor.black } override func draw(_ dirtyRect: NSRect) { super.draw(dirtyRect) // Custom drawing code here } func clearImage() { self.nameTextFiled.stringValue = "" self.nameTextFiled.font = NSFont.systemFont(ofSize: 14.0) if let callback = self.changeSignatureTextCallback { callback(false) } } func signatureImage() -> NSImage? { var rect = CGRect.zero let string = self.nameTextFiled.stringValue.isEmpty ? "" : self.nameTextFiled.stringValue let size = sizeOfString(string, withFontSize: self.nameTextFiled.font!) if size.width == 0 { return nil } else { rect = CGRect(x: kKMSignayureTextEdgeOffset, y: kKMSignayureTextEdgeOffset, width: size.width, height: size.height) } let image = NSImage(size: CGSize(width: size.width + kKMSignayureTextEdgeOffset * 2, height: size.height + kKMSignayureTextEdgeOffset * 2)) image.lockFocus() var dictionary = [NSAttributedString.Key: Any]() dictionary[NSAttributedString.Key.font] = self.nameTextFiled.font dictionary[NSAttributedString.Key.foregroundColor] = self.keyboardColor string.draw(in: rect, withAttributes: dictionary) image.unlockFocus() return image } func sizeOfString(_ string: String, withFontSize font: NSFont) -> CGSize { let dictionary: [NSAttributedString.Key: Any] = [ NSAttributedString.Key.font: font, NSAttributedString.Key.paragraphStyle: NSParagraphStyle.default ] let size = string.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: dictionary).size return size } func controlTextDidChange(_ obj: Notification) { if let textField = obj.object as? NSTextField, textField == self.nameTextFiled { let string = textField.stringValue.isEmpty ? nil : textField.stringValue var fontSize: CGFloat = 14.0 if string != nil { fontSize = kKMSignayureTextMaxFontSize } if let maxFont = NSFont(name: self.fontName, size: fontSize) { let size = sizeOfString(string ?? "", withFontSize: maxFont) let width = size.width + kKMSignayureTextEdgeOffset * 2 var scale: CGFloat = 1.0 scale = min((self.bounds.size.width - 30) / width, 60.0 / (size.height + 2)) if width >= 100 { self.labelWidthLayoutConstraint.constant = width } if let font = NSFont(name: self.fontName, size: fontSize) { self.nameTextFiled.font = font } let isTrue = !textField.stringValue.isEmpty if let callback = self.changeSignatureTextCallback { callback(isTrue) } if let delegate = self.delegate { delegate.changeSignatureText(isTrue) } } } } }