// // CDSignatureCertificateCustomViewController.swift // PDF Reader Pro Edition // // Created by Niehaoyu on 2023/10/12. // import Cocoa class CDSignatureCertificateCustomViewController: NSViewController, NSTextFieldDelegate { @IBOutlet weak var titleLabel: NSTextField! @IBOutlet weak var textButton: NSButton! @IBOutlet weak var textLineBox: NSBox! @IBOutlet weak var drawButton: NSButton! @IBOutlet weak var drawLineBox: NSBox! @IBOutlet weak var imageButton: NSButton! @IBOutlet weak var imageLineBox: NSBox! @IBOutlet weak var noneButton: NSButton! @IBOutlet weak var noneLineBox: NSBox! @IBOutlet weak var drawBox: NSBox! @IBOutlet weak var drawImageView: NSImageView! @IBOutlet weak var showDrawButton: NSButton! @IBOutlet weak var clearButton: NSButton! @IBOutlet weak var browseButton: NSButton! @IBOutlet weak var textLabel: NSTextField! @IBOutlet weak var nameButton: NSButton! @IBOutlet weak var dateButton: NSButton! @IBOutlet weak var logoButton: NSButton! @IBOutlet weak var reasonButton: NSButton! @IBOutlet weak var distinguishedButton: NSButton! @IBOutlet weak var versionButton: NSButton! @IBOutlet weak var locationButton: NSButton! @IBOutlet weak var labelsButton: NSButton! @IBOutlet weak var directionLabel: NSTextField! @IBOutlet weak var leftButton: NSButton! @IBOutlet weak var rightButton: NSButton! @IBOutlet weak var reasonLabel: NSTextField! @IBOutlet weak var reasonPopUpButton: NSPopUpButton! @IBOutlet weak var locationLabel: NSTextField! @IBOutlet weak var locationTextField: NSTextField! @IBOutlet weak var nameLabel: NSTextField! @IBOutlet weak var nameTextField: NSTextField! @IBOutlet weak var cancelButton: NSButton! @IBOutlet weak var continueButton: NSButton! @IBOutlet weak var locationTopOffset: NSLayoutConstraint! var _customType: CDSignatureCustomType = .none var signatureWidget: CPDFSignatureWidgetAnnotation! var appearanceData: DSignatureAppearanceData! var cert: KMDSignatureModel! var isCreat: Bool = false var photoImage: NSImage! var drawImage: NSImage! var drawText: String! var drawViewController = CDSignatureDrawViewController.init() var textViewController = CDSignatureTextViewController.init() var actionBlock: ((_ customVC: CDSignatureCertificateCustomViewController, _ type: DSignatureActionType, _ appearanceData: DSignatureAppearanceData)->Void)? override func viewWillAppear() { super.viewWillAppear() self.logoButton.state = .off; self.labelsButton.state = .off self.distinguishedButton.state = .off self.nameButton.state = .off self.reasonButton.state = .off self.locationButton.state = .off self.dateButton.state = .off self.versionButton.state = .off self.reasonLabel.isHidden = true self.reasonPopUpButton.isHidden = true self.locationLabel.isHidden = true self.locationTextField.isHidden = true self.locationTextField.delegate = self if (self.isCreat) { self.nameTextField.stringValue = ""; self.appearanceData = DSignatureApperanceManager.manager.standardDSignatureAppearanceData() if self.cert.name.isEmpty == false { self.appearanceData.signatureConfig.text = self.cert.name } } else { if self.appearanceData.appearanceName.length > 0 { self.nameTextField.stringValue = self.appearanceData.appearanceName as String } else { self.nameTextField.stringValue = "" } } if (self.appearanceData.signatureConfig.isDrawLogo) { self.logoButton.state = .on; } if (self.appearanceData.signatureConfig.isDrawKey) { self.labelsButton.state = .on; } let keys = NSMutableArray() for item in self.appearanceData.signatureConfig.contents { keys.add(item.key as String) } if keys.contains(DN_KEY) { self.distinguishedButton.state = .on } if keys.contains(kNAME_KEY) { self.nameButton.state = .on } if keys.contains(REASON_KEY) { self.reasonButton.state = .on self.reasonLabel.isHidden = false self.reasonPopUpButton.isHidden = false } if keys.contains(LOCATION_KEY) { self.locationButton.state = .on self.locationTextField.isHidden = false self.locationLabel.isHidden = false if self.reasonButton.state == .on { self.locationTopOffset.constant = 56; } else { self.locationTopOffset.constant = 12; } var valueString = String() for item in self.appearanceData.signatureConfig.contents { if item.key == LOCATION_KEY { valueString = item.value break } } self.locationTextField.stringValue = valueString } if keys.contains(DATE_KEY) { self.dateButton.state = .on } if keys.contains(VERSION_KEY) { self.versionButton.state = .on } if (self.appearanceData.signatureConfig.isContentAlginLeft) { self.leftButton.image = NSImage(named: "ImageNamePropertybarTextalignLeftNor") self.rightButton.image = NSImage(named: "ImageNamePropertybarTextalignRightSel") } else { self.leftButton.image = NSImage(named: "ImageNamePropertybarTextalignLeftSel") self.rightButton.image = NSImage(named: "ImageNamePropertybarTextalignRightNor"); } if (self.appearanceData.drawType == .image) { self.photoImage = self.appearanceData.signatureConfig.image } else if (self.appearanceData.drawType == .draw) { self.drawImage = self.appearanceData.signatureConfig.image } else if (self.appearanceData.drawType == .text) { self.drawText = self.appearanceData.signatureConfig.text } self.customType = self.appearanceData.drawType self.reloadData() } override func viewDidLoad() { super.viewDidLoad() // Do view setup here. self.localizedLanguage() self.reasonLabel.isHidden = true self.reasonPopUpButton.isHidden = true self.locationLabel.isHidden = true self.locationTextField.isHidden = true self.textLineBox.isHidden = true self.imageLineBox.isHidden = true self.drawLineBox.isHidden = true self.noneLineBox.isHidden = true self.textLineBox.fillColor = KMAppearance.Layout.mColor() self.imageLineBox.fillColor = KMAppearance.Layout.mColor() self.drawLineBox.fillColor = KMAppearance.Layout.mColor() self.noneLineBox.fillColor = KMAppearance.Layout.mColor() self.titleLabel.textColor = NSColor.labelColor self.nameLabel.textColor = NSColor.labelColor self.drawBox.borderColor = NSColor(red: 165.0/255.0, green: 167.0/255.0, blue: 179.0/255.0, alpha: 1.0) self.reasonLabel.textColor = NSColor.labelColor self.locationLabel.textColor = NSColor.labelColor self.locationTextField.textColor = NSColor.labelColor self.nameTextField.textColor = NSColor.labelColor self.leftButton.wantsLayer = true self.rightButton.wantsLayer = true self.leftButton.layer?.cornerRadius = 5.0 self.rightButton.layer?.cornerRadius = 5.0 self.locationTextField.delegate = self; self.textViewController.actionBlock = { textVC, inputText in if inputText.count > 0 { self.drawText = inputText } else { self.drawText = "" } self.appearanceData.isInputDSignatureText = true self.appearanceData.signatureConfig.text = self.drawText self.reloadData() } self.drawViewController.actionBlock = { drawVC, image in if image.size.width > 0 && image.size.height > 0 { self.drawImage = image self.appearanceData.signatureConfig.image = image } self.reloadData() } } //MARK: Setter var customType: CDSignatureCustomType { set { _customType = newValue; let norColor = KMAppearance.Layout.h1Color() let selColor = KMAppearance.Layout.mColor() self.appearanceData.drawType = _customType self.appearanceData.signatureConfig.isDrawOnlyContent = false self.textLineBox.isHidden = true self.imageLineBox.isHidden = true self.noneLineBox.isHidden = true self.drawLineBox.isHidden = true self.textButton.setTitleColor(norColor) self.drawButton.setTitleColor(norColor) self.imageButton.setTitleColor(norColor) self.noneButton.setTitleColor(norColor) if self.customType == .draw { self.drawLineBox.isHidden = false self.drawButton.setTitleColor(selColor) self.textButton.image = NSImage(named: "ImageNameDSignatureCustomText") self.drawButton.image = NSImage(named: "ImageNameDSignatureCustomSignSelect") self.imageButton.image = NSImage(named: "ImageNameDSignatureCustomImage") self.noneButton.image = NSImage(named: "ImageNameDSignatureCustomNone") self.showDrawButton.isHidden = false self.browseButton.isHidden = true self.clearButton.isHidden = true self.appearanceData.signatureConfig.text = nil; self.appearanceData.signatureConfig.image = self.drawImage; } else if self.customType == .image { self.imageLineBox.isHidden = false; self.imageButton.setTitleColor(selColor) self.textButton.image = NSImage(named: "ImageNameDSignatureCustomText") self.drawButton.image = NSImage(named: "ImageNameDSignatureCustomSign") self.imageButton.image = NSImage(named: "ImageNameDSignatureCustomImageSelect") self.noneButton.image = NSImage(named: "ImageNameDSignatureCustomNone") self.showDrawButton.isHidden = true self.browseButton.isHidden = false self.clearButton.isHidden = false self.appearanceData.signatureConfig.text = nil self.appearanceData.signatureConfig.image = self.photoImage } else if self.customType == .none { self.noneLineBox.isHidden = false self.noneButton.setTitleColor(selColor) self.textButton.image = NSImage(named: "ImageNameDSignatureCustomText") self.drawButton.image = NSImage(named: "ImageNameDSignatureCustomSign") self.imageButton.image = NSImage(named: "ImageNameDSignatureCustomImage") self.noneButton.image = NSImage(named: "ImageNameDSignatureCustomNoneSelect") self.showDrawButton.isHidden = true; self.browseButton.isHidden = true; self.clearButton.isHidden = true; self.appearanceData.signatureConfig.text = nil; self.appearanceData.signatureConfig.image = nil; self.appearanceData.signatureConfig.isDrawOnlyContent = true; } else if self.customType == .text { self.textLineBox.isHidden = false self.textButton.setTitleColor(selColor) self.textButton.image = NSImage(named: "ImageNameDSignatureCustomTextSelect") self.drawButton.image = NSImage(named: "ImageNameDSignatureCustomSign") self.imageButton.image = NSImage(named: "ImageNameDSignatureCustomImage") self.noneButton.image = NSImage(named: "ImageNameDSignatureCustomNone") self.showDrawButton.isHidden = true; self.browseButton.isHidden = true; self.clearButton.isHidden = true; self.appearanceData.signatureConfig.image = nil; self.appearanceData.signatureConfig.text = self.drawText } self.reloadData() } get { return _customType; } } //MARK: Method func localizedLanguage() { self.titleLabel.stringValue = NSLocalizedString("Customize the Signature Appearance", comment: "") self.nameLabel.stringValue = NSLocalizedString("Preset Name", comment: "") + ":" self.textButton.title = NSLocalizedString("Text", comment: ""); self.imageButton.title = NSLocalizedString("Image", comment: ""); self.drawButton.title = NSLocalizedString("Draw", comment: ""); self.noneButton.title = NSLocalizedString("None", comment: ""); self.browseButton.title = NSLocalizedString("Browse", comment: ""); self.clearButton.title = NSLocalizedString("Clear", comment: ""); self.showDrawButton.title = NSLocalizedString("Click here to draw", comment: ""); let txtColor = KMAppearance.Interactive.a0Color() self.browseButton.setTitleColor(txtColor) self.clearButton.setTitleColor(txtColor) self.showDrawButton.setTitleColor(txtColor) self.continueButton.title = NSLocalizedString("Continue", comment: ""); self.cancelButton.title = NSLocalizedString("Cancel", comment: ""); self.textLabel.stringValue = NSLocalizedString("Include Text", comment: ""); self.directionLabel.stringValue = String(format: "%@:",NSLocalizedString("Text Alignment", comment: "")); self.nameButton.title = NSLocalizedString("Name", comment: ""); self.dateButton.title = NSLocalizedString("Date", comment: ""); self.locationButton.title = NSLocalizedString("Location", comment: ""); self.reasonButton.title = NSLocalizedString("Reason", comment: ""); self.distinguishedButton.title = NSLocalizedString("Distinguished Name", comment: ""); self.versionButton.title = VERSION_KEY self.logoButton.title = NSLocalizedString("Logo", comment: ""); self.labelsButton.title = NSLocalizedString("Include Text", comment: ""); self.locationLabel.stringValue = String(format:"%@:",NSLocalizedString("Location", comment: "")); self.reasonLabel.stringValue = String(format:"%@:",NSLocalizedString("Reason", comment: "")); let titles = [String(format:" %@",NSLocalizedString("none", comment: "")), String(format:" %@",NSLocalizedString("I am the author of this document", comment: "")), String(format:" %@",NSLocalizedString("I have reviewed this document", comment: "")), String(format:" %@",NSLocalizedString("I'm in the process of approving this document", comment: "")), String(format:" %@",NSLocalizedString("I certify the accuracy and authenticity of this document", comment: "")), String(format:" %@",NSLocalizedString("I have signed this document to indicate that I agree to the terms defined", comment: "")), String(format:" %@",NSLocalizedString("I agree with the specified portions of this document", comment: ""))] self.reasonPopUpButton.addItems(withTitles: titles) } func reloadData() { for item in self.appearanceData.signatureConfig.contents { if item.key == DATE_KEY { let dateFormatter = DateFormatter.init() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" let dateString = dateFormatter.string(from: NSDate() as Date) item.value = dateString break } } self.signatureWidget.signAppearanceConfig(self.appearanceData.signatureConfig) let image: NSImage = self.signatureWidget.contentImage() self.drawImageView.image = image } //MARK: IBAction @IBAction func closeAction(_ sender: Any) { guard let callBack = self.actionBlock else { return } callBack(self, .cancel, DSignatureAppearanceData()) } @IBAction func buttonItemClick_CustomType(_ sender: NSButton) { self.customType = CDSignatureCustomType(rawValue: sender.tag) ?? .none; if (self.customType == .text) { // self.textViewController.drawText = self.drawText // self.presentAsSheet(self.textViewController) } else if self.customType == .draw { self.buttonItemClick_ShowDraw(self.drawButton) } } @IBAction func buttonItemClick_ShowDraw(_ sender: NSButton) { self.drawViewController.drawImage = self.drawImage; self.presentAsSheet(self.drawViewController) } @IBAction func buttonItemClick_Clear(_ sender: Any) { self.photoImage = nil self.appearanceData.signatureConfig.image = nil self.reloadData() } @IBAction func buttonItemClick_Browse(_ sender: Any) { let openPanel = NSOpenPanel() openPanel.canChooseDirectories = false openPanel.canChooseFiles = true openPanel.allowsMultipleSelection = false; openPanel.allowedFileTypes = KMPDFSignatureImageView().supportedImageTypes() openPanel.beginSheetModal(for: self.view.window!) { result in if result == .OK { let fileURL = openPanel.urls.first let filePath: String = fileURL!.path if self.isPDFFile(atPath: filePath) == true { let document = CPDFDocument(url: fileURL) if !document!.allowsCopying || !document!.allowsPrinting { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("This is a secured document. Editing is not permitted.", comment: "") alert.runModal() return } } self.appearanceData.signatureConfig.text = "" self.photoImage = NSImage(contentsOf: fileURL!) self.appearanceData.signatureConfig.image = self.photoImage self.reloadData() } } } @IBAction func buttonItemClick_ShowText(_ sender: Any) { let contents = NSMutableArray(array: self.appearanceData.signatureConfig.contents) if contents.count <= 1 && self.customType == .none { let configItem: CPDFSignatureConfigItem = contents.firstObject as! CPDFSignatureConfigItem if configItem.key == kNAME_KEY && self.appearanceData.signatureConfig.isDrawKey { if self.nameButton.state == .off { contents.removeAllObjects() } if self.labelsButton.state == .off { self.appearanceData.signatureConfig.isDrawKey = false } } } var configItem: CPDFSignatureConfigItem! if self.nameButton.isEqual(sender) { if self.nameButton.state == .on { configItem = CPDFSignatureConfigItem.init() configItem.key = kNAME_KEY configItem.value = NSLocalizedString("", comment: "") contents.add(configItem as Any) } else { for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == kNAME_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.dateButton.isEqual(sender) { if self.dateButton.state == .on { configItem = CPDFSignatureConfigItem.init() configItem.key = DATE_KEY let dateFormatter = DateFormatter.init() dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" configItem.value = dateFormatter.string(from: NSDate() as Date) contents.add(configItem as Any) } else { for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == DATE_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.reasonButton.isEqual(sender) { if (self.reasonButton.state == .on) { self.locationTopOffset.constant = 56.0; } else { self.locationTopOffset.constant = 12.0; } if self.reasonButton.state == .on { self.reasonPopUpButton.isHidden = false self.reasonLabel.isHidden = false self.reasonPopUpButton.selectItem(at: 0) configItem = CPDFSignatureConfigItem.init() configItem.key = REASON_KEY configItem.value = self.reasonPopUpButton.title if configItem.value == "" || configItem.value == String(format: " %@", NSLocalizedString("none", comment: "")) { configItem.value = NSLocalizedString("", comment: "") } contents.add(configItem as Any) } else { self.reasonPopUpButton.isHidden = true self.reasonLabel.isHidden = true for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == REASON_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.locationButton.isEqual(sender) { if self.locationButton.state == .on { self.locationLabel.isHidden = false self.locationTextField.isHidden = false if (self.reasonButton.state == .on) { self.locationTopOffset.constant = 56.0; } else { self.locationTopOffset.constant = 12.0; } configItem = CPDFSignatureConfigItem.init() configItem.key = LOCATION_KEY if self.locationTextField.stringValue.isEmpty { configItem.value = NSLocalizedString("", comment: "") } else { configItem.value = self.locationTextField.stringValue } contents.add(configItem as Any) } else { self.locationLabel.isHidden = true self.locationTextField.isHidden = true for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == LOCATION_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.distinguishedButton.isEqual(sender) { if self.distinguishedButton.state == .on { configItem = CPDFSignatureConfigItem.init() configItem.key = DN_KEY configItem.value = NSLocalizedString("", comment: "") contents.add(configItem as Any) } else { for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == DN_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.versionButton.isEqual(sender) { if self.versionButton.state == .on { configItem = CPDFSignatureConfigItem.init() configItem.key = VERSION_KEY let infoDictionary = Bundle.main.infoDictionary! // CFShow(infoDictionary) let app_Version = infoDictionary["CFBundleShortVersionString"] configItem.value = app_Version as? String contents.add(configItem as Any) } else { for item in contents { let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem if exitItem.key == VERSION_KEY { configItem = item as? CPDFSignatureConfigItem break } } if configItem != nil { contents.remove(configItem as Any) } } } else if self.logoButton.isEqual(sender) { if self.logoButton.state == .on { self.appearanceData.signatureConfig.isDrawLogo = true } else { self.appearanceData.signatureConfig.isDrawLogo = false } }else if self.labelsButton.isEqual(sender) { if self.labelsButton.state == .on { self.appearanceData.signatureConfig.isDrawKey = true } else { self.appearanceData.signatureConfig.isDrawKey = false } } if self.customType == .none && contents.count == 0 { configItem = CPDFSignatureConfigItem.init() configItem.key = kNAME_KEY configItem.value = NSLocalizedString("", comment: "") contents.add(configItem as Any) self.appearanceData.signatureConfig.isDrawKey = true } let sortContents:[Any] = KMDSignatureManager.default().sortContens((contents as! [Any])) self.appearanceData.signatureConfig.contents = (sortContents as! [CPDFSignatureConfigItem]) self.reloadData() } @IBAction func buttonItemClick_Algin(_ sender: NSButton) { if (sender.tag == 0) { self.appearanceData.signatureConfig.isContentAlginLeft = false; self.leftButton.image = NSImage(named: "ImageNamePropertybarTextalignLeftSel") self.rightButton.image = NSImage(named: "ImageNamePropertybarTextalignRightNor") } else { self.appearanceData.signatureConfig.isContentAlginLeft = true; self.leftButton.image = NSImage(named: "ImageNamePropertybarTextalignLeftNor") self.rightButton.image = NSImage(named: "ImageNamePropertybarTextalignRightSel") } self.reloadData() } @IBAction func buttonItemClick_Reason(_ sender: Any) { let contents:[CPDFSignatureConfigItem] = self.appearanceData.signatureConfig.contents for object in contents { if object.key == REASON_KEY { if self.reasonPopUpButton.title.count > 2 { let fromStr = self.reasonPopUpButton.title.dropFirst(2) if self.reasonPopUpButton.title == String(format: " %@", NSLocalizedString("none", comment: "")) { object.value = NSLocalizedString("", comment: "") } else { object.value = String(fromStr) } } break } } self.reloadData() } @IBAction func buttonItemClick_Cancel(_ sender: Any) { guard let callBack = self.actionBlock else { return } callBack(self, .previousStep, DSignatureAppearanceData()) } @IBAction func buttonItemClick_Continue(_ sender: Any) { let name = self.nameTextField.stringValue if (self.isCreat) { let at: [DSignatureAppearanceData] = DSignatureApperanceManager.manager.signatures as! [DSignatureAppearanceData] var names = NSMutableArray() for data in at { names.add(data.appearanceName as Any) } if names.contains(name) { let alert = NSAlert.init() alert.messageText = NSLocalizedString("The name already exists, please enter it again!", comment: "") alert.addButton(withTitle: NSLocalizedString("OK", comment: "")) alert.runModal() return } self.appearanceData.tag = DSignatureApperanceManager.manager.tagString() } if name.count > 0 { self.appearanceData.appearanceName = self.nameTextField.stringValue as NSString } else { self.appearanceData.appearanceName = DSignatureApperanceManager.manager.tagString() } guard let callBack = self.actionBlock else { return } callBack(self, .confirm, self.appearanceData) } //MARK: NSTextFieldDelegate func controlTextDidChange(_ obj: Notification) { if obj.object == nil { return } let textField = obj.object as! NSTextField if self.locationTextField.isEqual(textField) { let contents = self.appearanceData.signatureConfig.contents! for object in contents { if object.key == LOCATION_KEY { if self.locationTextField.stringValue.isEmpty == true { object.value = NSLocalizedString("", comment: "") } else { object.value = self.locationTextField.stringValue } break } } self.reloadData() } } func isPDFFile(atPath path: String) -> Bool { let fileURL = URL(fileURLWithPath: path) if let fileExtension = fileURL.pathExtension.lowercased() as? String { return fileExtension == "pdf" } return false } }