|
@@ -0,0 +1,686 @@
|
|
|
+//
|
|
|
+// KMAnnotationLinkViewController.swift
|
|
|
+// PDF Master
|
|
|
+//
|
|
|
+// Created by wanjun on 2023/10/11.
|
|
|
+//
|
|
|
+
|
|
|
+import Cocoa
|
|
|
+
|
|
|
+let URLPlaceholder = "https://www.pdfreaderpro.com"
|
|
|
+let EmailPlaceholder = "support@pdfreaderpro.com"
|
|
|
+
|
|
|
+enum KMAnnotationLinkType: Int {
|
|
|
+ case Page
|
|
|
+ case URL
|
|
|
+ case Email
|
|
|
+}
|
|
|
+
|
|
|
+enum KMAnnotationLinkState: Int {
|
|
|
+ case Normal
|
|
|
+ case Hover
|
|
|
+ case Selected
|
|
|
+}
|
|
|
+
|
|
|
+class KMAnnotationLinkViewController: KMAnnotationPropertyBaseController {
|
|
|
+
|
|
|
+ var annotationModel: CPDFAnnotationModel?
|
|
|
+ var _content: String = ""
|
|
|
+ var pageCount: Int = 0
|
|
|
+ var _isCreateLink: Bool = false
|
|
|
+
|
|
|
+ @IBOutlet weak var linkStyleView: NSView!
|
|
|
+ @IBOutlet var linkPageBox: KMBox!
|
|
|
+ @IBOutlet var linkPageImageView: NSImageView!
|
|
|
+ @IBOutlet weak var pageImageThumible: NSImageView!
|
|
|
+ @IBOutlet weak var targetButton: KMCoverButton!
|
|
|
+ @IBOutlet weak var targetLabel: NSTextField!
|
|
|
+ @IBOutlet weak var tagrgetBox: NSBox!
|
|
|
+
|
|
|
+ @IBOutlet var linkUrlBox: KMBox!
|
|
|
+ @IBOutlet var linkUrlImageView: NSImageView!
|
|
|
+
|
|
|
+ @IBOutlet var linkEmailBox: KMBox!
|
|
|
+ @IBOutlet var linkEmailImageView: NSImageView!
|
|
|
+
|
|
|
+ @IBOutlet var contentBox: NSBox!
|
|
|
+
|
|
|
+ @IBOutlet var urlView: NSView!
|
|
|
+ @IBOutlet var urlLabel: NSTextField!
|
|
|
+ @IBOutlet var inputUrlTextField: NSTextField!
|
|
|
+ @IBOutlet weak var inputUrlBox: NSBox!
|
|
|
+
|
|
|
+ @IBOutlet var goButton: NSButton!
|
|
|
+ @IBOutlet var errorLabel: NSTextField!
|
|
|
+ @IBOutlet weak var goButtonTopComstraint: NSLayoutConstraint!
|
|
|
+
|
|
|
+ var annotation: CPDFLinkAnnotation?
|
|
|
+ var _linkType: KMAnnotationLinkType = .Page
|
|
|
+ var mouseDownBox: KMBox?
|
|
|
+ var pageRecord: String = ""
|
|
|
+ var urlRecord: String = ""
|
|
|
+ var emailRecord: String = ""
|
|
|
+ var startPage: String = ""
|
|
|
+ var isGo: Bool = false
|
|
|
+
|
|
|
+ var boxNormalBorderColor: NSColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1)
|
|
|
+ var boxErrorBorderColor: NSColor = NSColor(red: 243/255.0, green: 70/255.0, blue: 91/255.0, alpha: 1)
|
|
|
+ var targetButtonState: KMAnnotationLinkState = .Normal
|
|
|
+
|
|
|
+
|
|
|
+ //MARK: Init Methods
|
|
|
+
|
|
|
+ override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
|
|
|
+ super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
|
|
+
|
|
|
+ self.boxNormalBorderColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1)
|
|
|
+ self.boxErrorBorderColor = NSColor(red: 243/255.0, green: 70/255.0, blue: 91/255.0, alpha: 1)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ required init?(coder: NSCoder) {
|
|
|
+ super.init(coder: coder)
|
|
|
+ }
|
|
|
+
|
|
|
+ deinit {
|
|
|
+ NotificationCenter.default.removeObserver(self)
|
|
|
+ inputUrlTextField.delegate = nil
|
|
|
+
|
|
|
+ print("\(#function)")
|
|
|
+ }
|
|
|
+
|
|
|
+ //MARK: View Methods
|
|
|
+ override func viewDidLoad() {
|
|
|
+ super.viewDidLoad()
|
|
|
+ // Do view setup here.
|
|
|
+
|
|
|
+ self.annotation = self.annotationModel?.annotation as? CPDFLinkAnnotation
|
|
|
+
|
|
|
+ self.pageRecord = ""
|
|
|
+ self.urlRecord = ""
|
|
|
+ self.emailRecord = ""
|
|
|
+
|
|
|
+ self.linkStyleView.wantsLayer = true
|
|
|
+ self.linkPageImageView.wantsLayer = true
|
|
|
+ self.linkUrlImageView.wantsLayer = true
|
|
|
+ self.linkEmailImageView.wantsLayer = true
|
|
|
+
|
|
|
+ self.linkStyleView.layer?.backgroundColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1.0).cgColor
|
|
|
+ self.linkStyleView.layer?.cornerRadius = 6.0
|
|
|
+ self.linkStyleView.layer?.masksToBounds = true
|
|
|
+
|
|
|
+ let boxArr: [KMBox] = [linkPageBox, linkUrlBox, linkEmailBox]
|
|
|
+ for box in boxArr {
|
|
|
+ box.downCallback = { [weak self] downEntered, mouseBox, event in
|
|
|
+ guard let self = self else { return }
|
|
|
+ if downEntered {
|
|
|
+ if self.mouseDownBox === mouseBox {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var mouseDownInt = 0
|
|
|
+ if self.linkPageBox === mouseBox {
|
|
|
+ self.inputUrlTextField.stringValue = ""
|
|
|
+ self.linkType = .Page
|
|
|
+ mouseDownInt = 0
|
|
|
+ } else if self.linkUrlBox === mouseBox {
|
|
|
+ self.inputUrlTextField.stringValue = ""
|
|
|
+ self.linkType = .URL
|
|
|
+ mouseDownInt = 1
|
|
|
+ } else if self.linkEmailBox === mouseBox {
|
|
|
+ self.inputUrlTextField.stringValue = ""
|
|
|
+ self.linkType = .Email
|
|
|
+ mouseDownInt = 2
|
|
|
+ }
|
|
|
+ UserDefaults.standard.set(mouseDownInt, forKey: "kmLinkSelectIndex")
|
|
|
+ UserDefaults.standard.synchronize()
|
|
|
+ self.mouseDownBox = mouseBox
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.isGo = true
|
|
|
+ self.targetLabel.stringValue = NSLocalizedString("Locate the target page", tableName: "MainMenu", comment: "")
|
|
|
+ self.inputUrlTextField.wantsLayer = true
|
|
|
+ self.inputUrlTextField.focusRingType = .none
|
|
|
+ self.linkPageImageView.layer?.cornerRadius = 4.0
|
|
|
+ self.linkUrlImageView.layer?.cornerRadius = 4.0
|
|
|
+ self.linkEmailImageView.layer?.cornerRadius = 4.0
|
|
|
+ let inputUrlTextFieldCell = self.inputUrlTextField.cell as! NSTextFieldCell
|
|
|
+ inputUrlTextFieldCell.allowedInputSourceLocales = [NSAllRomanInputSourcesLocaleIdentifier]
|
|
|
+
|
|
|
+ if self.linkType == .Email {
|
|
|
+ self.linkType = .Email
|
|
|
+ self.mouseDownBox = linkEmailBox
|
|
|
+ } else if linkType == .URL {
|
|
|
+ self.linkType = .URL
|
|
|
+ self.mouseDownBox = linkUrlBox
|
|
|
+ } else if linkType == .Page {
|
|
|
+ self.linkType = .Page
|
|
|
+ self.mouseDownBox = linkPageBox
|
|
|
+ }
|
|
|
+
|
|
|
+ self.targetButton.coverAction = { [weak self] button, action in
|
|
|
+ guard let self = self, self.targetButtonState != .Selected else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if action == .enter {
|
|
|
+ self.updateTargetBoxState(state: .Hover)
|
|
|
+ } else if action == .exit {
|
|
|
+ self.updateTargetBoxState(state: .Normal)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [weak self] event in
|
|
|
+ guard let self = self else { return event }
|
|
|
+ if event.keyCode == 53 {
|
|
|
+ if self.inputUrlTextField.isEditable {
|
|
|
+ self.pdfview?.annotationType = .unkown
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return event
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override func viewDidAppear() {
|
|
|
+ super.viewDidAppear()
|
|
|
+
|
|
|
+ self.inputUrlTextField.delegate = self
|
|
|
+ }
|
|
|
+
|
|
|
+ override func setupUI() {
|
|
|
+ super.setupUI()
|
|
|
+
|
|
|
+ let fontName = "SFProText-Regular"
|
|
|
+
|
|
|
+ self.urlLabel.font = NSFont(name: fontName, size: 12)
|
|
|
+ self.urlLabel.textColor = NSColor(red: 97.0/255.0, green: 100.0/255.0, blue: 105.0/255.0, alpha: 1)
|
|
|
+
|
|
|
+ self.inputUrlBox.borderColor = self.boxNormalBorderColor
|
|
|
+ self.inputUrlBox.fillColor = NSColor.white
|
|
|
+ self.errorLabel.textColor = self.boxErrorBorderColor
|
|
|
+ self.errorLabel.font = NSFont(name: fontName, size: 12)
|
|
|
+
|
|
|
+ self.tagrgetBox.fillColor = NSColor.white
|
|
|
+ self.updateTargetBoxState(state: .Normal)
|
|
|
+ self.targetLabel.font = NSFont(name: fontName, size: 14)
|
|
|
+ self.targetLabel.textColor = NSColor(red: 37/255.0, green: 38/255.0, blue: 41/255.0, alpha: 1)
|
|
|
+
|
|
|
+ self.goButton.title = NSLocalizedString("Go", comment: "")
|
|
|
+ self.goButton.attributedTitle = NSAttributedString(string: self.goButton.title, attributes: [.foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)])
|
|
|
+ }
|
|
|
+
|
|
|
+ //MARK: Set、Get
|
|
|
+
|
|
|
+ var linkType: KMAnnotationLinkType {
|
|
|
+ get {
|
|
|
+ return _linkType
|
|
|
+ }
|
|
|
+ set {
|
|
|
+ _linkType = newValue
|
|
|
+ switch _linkType {
|
|
|
+ case .Page:
|
|
|
+ self.createLinkPageView()
|
|
|
+ self.inputUrlTextField.becomeFirstResponder()
|
|
|
+ case .URL:
|
|
|
+ self.createLinkURLView()
|
|
|
+ self.inputUrlTextField.becomeFirstResponder()
|
|
|
+ case .Email:
|
|
|
+ self.createLinkEmailView()
|
|
|
+ self.inputUrlTextField.becomeFirstResponder()
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var content: String {
|
|
|
+ get {
|
|
|
+ return _content
|
|
|
+ }
|
|
|
+ set {
|
|
|
+ _content = newValue
|
|
|
+
|
|
|
+ if _content != "" {
|
|
|
+ if _content.count > 0 {
|
|
|
+ let typeLocal = _content.first ?? Character("\0")
|
|
|
+ if typeLocal == "0" {
|
|
|
+ _content = (_content as NSString).substring(from: 1)
|
|
|
+ self.linkType = .Page
|
|
|
+ self.inputUrlTextField.stringValue = _content
|
|
|
+ self.mouseDownBox = self.linkPageBox
|
|
|
+ } else {
|
|
|
+ if content.dropFirst().hasPrefix("mailto:") {
|
|
|
+ _content = (_content as NSString).substring(from: 8)
|
|
|
+ self.linkType = .Email
|
|
|
+ self.mouseDownBox = self.linkEmailBox
|
|
|
+ } else {
|
|
|
+ _content = (_content as NSString).substring(from: 1)
|
|
|
+ self.linkType = .URL
|
|
|
+ self.mouseDownBox = self.linkUrlBox
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ _content = "http://"
|
|
|
+ self.linkType = .URL
|
|
|
+ self.mouseDownBox = self.linkUrlBox
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override var pdfview: CPDFListView? {
|
|
|
+ get {
|
|
|
+ return _pdfview
|
|
|
+ }
|
|
|
+ set {
|
|
|
+ _pdfview = newValue
|
|
|
+ self.startPage = String(format: "%ld", _pdfview!.currentPageIndex+1)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var isCreateLink: Bool {
|
|
|
+ get {
|
|
|
+ return _isCreateLink
|
|
|
+ }
|
|
|
+ set {
|
|
|
+ _isCreateLink = newValue
|
|
|
+ if _isCreateLink {
|
|
|
+ self.linkType = .Page
|
|
|
+ self.mouseDownBox = self.linkPageBox
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //MARK: private
|
|
|
+
|
|
|
+ func createLinkPageView() {
|
|
|
+ self.annotationLinkSelectBox(self.linkPageBox)
|
|
|
+ self.urlLabel.stringValue = NSLocalizedString("Page", comment: "")
|
|
|
+
|
|
|
+ self.inputUrlTextField.formatter = TextFieldFormatter()
|
|
|
+ if self.pdfview!.document?.pageCount ?? 0 > 1 {
|
|
|
+ self.inputUrlTextField.placeholderString = NSLocalizedString("Enter target page", comment: "")
|
|
|
+ } else {
|
|
|
+ self.inputUrlTextField.placeholderString = "1"
|
|
|
+ }
|
|
|
+
|
|
|
+ if let destination = self.annotation!.destination() {
|
|
|
+ let pageIndex = destination.pageIndex
|
|
|
+ self.inputUrlTextField.stringValue = "\(pageIndex + 1)"
|
|
|
+ self.pageRecord = "\(pageIndex + 1)"
|
|
|
+ } else {
|
|
|
+ self.pageRecord = "1"
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.inputUrlTextField.stringValue.count == 0 {
|
|
|
+ self.inputUrlTextField.stringValue = self.pageRecord
|
|
|
+ }
|
|
|
+
|
|
|
+ self.tagrgetBox.isHidden = false
|
|
|
+ self.pageImageThumible.isHidden = true
|
|
|
+ self.goButton.isHidden = true
|
|
|
+ self.goButtonTopComstraint.constant = 20
|
|
|
+ self.errorLabel.stringValue = NSLocalizedString("Page number out of range", comment: "")
|
|
|
+
|
|
|
+ if self.inputUrlTextField.stringValue.count == 0 {
|
|
|
+
|
|
|
+ } else {
|
|
|
+ if let dexPage = Int(self.inputUrlTextField.stringValue) {
|
|
|
+ self.dealThumibleImage(dexPage: UInt(dexPage))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func createLinkURLView() {
|
|
|
+ self.annotationLinkSelectBox(self.linkUrlBox)
|
|
|
+ self.urlLabel.stringValue = NSLocalizedString("URL:", comment: "")
|
|
|
+
|
|
|
+ self.inputUrlTextField.formatter = nil
|
|
|
+ self.inputUrlTextField.placeholderString = "https://www.pdfreaderpro.com"
|
|
|
+
|
|
|
+ if let urlString = self.annotation?.url() {
|
|
|
+ var modifiedURL = urlString
|
|
|
+ if modifiedURL.hasPrefix("http://") {
|
|
|
+ modifiedURL = (modifiedURL as NSString).substring(from: 7)
|
|
|
+ } else if modifiedURL.hasPrefix("https://://") {
|
|
|
+ modifiedURL = (modifiedURL as NSString).substring(from: 8)
|
|
|
+ }
|
|
|
+ self.inputUrlTextField.stringValue = modifiedURL
|
|
|
+ self.urlRecord = modifiedURL
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.inputUrlTextField.stringValue.count == 0 {
|
|
|
+ self.inputUrlTextField.stringValue = self.urlRecord
|
|
|
+ }
|
|
|
+
|
|
|
+ self.tagrgetBox.isHidden = true
|
|
|
+ self.pageImageThumible.isHidden = true
|
|
|
+ self.goButton.isHidden = true
|
|
|
+ self.goButtonTopComstraint.constant = -390
|
|
|
+ self.errorLabel.stringValue = NSLocalizedString("Invalid Email. Please re-enter correct email.", comment: "")
|
|
|
+ self.goButton.title = NSLocalizedString("Go", comment: "")
|
|
|
+ self.goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [NSAttributedString.Key.foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)])
|
|
|
+
|
|
|
+ if self.inputUrlTextField.stringValue.count > 0 {
|
|
|
+ self.goButton.isHidden = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func createLinkEmailView() {
|
|
|
+ self.annotationLinkSelectBox(self.linkEmailBox)
|
|
|
+ self.urlLabel.stringValue = NSLocalizedString("Email:", comment: "")
|
|
|
+ self.inputUrlTextField.formatter = nil
|
|
|
+ self.inputUrlTextField.placeholderString = "support@pdfreaderpro.com"
|
|
|
+
|
|
|
+ if let urlString = annotation?.url(), urlString.contains("mailto") {
|
|
|
+ if urlString.hasPrefix("mailto:") {
|
|
|
+ let email = String(urlString.suffix(from: urlString.index(urlString.startIndex, offsetBy: 7)))
|
|
|
+ inputUrlTextField.stringValue = email
|
|
|
+ emailRecord = email
|
|
|
+ }
|
|
|
+
|
|
|
+ if inputUrlTextField.stringValue.isEmpty {
|
|
|
+ inputUrlTextField.stringValue = emailRecord
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ tagrgetBox.isHidden = true
|
|
|
+ pageImageThumible.isHidden = true
|
|
|
+ goButton.isHidden = true
|
|
|
+ goButtonTopComstraint.constant = -390
|
|
|
+ errorLabel.stringValue = NSLocalizedString("Invalid Email. Please re-enter correct email.", comment: "")
|
|
|
+ goButton.title = NSLocalizedString("Go", comment: "")
|
|
|
+ goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
|
|
|
+ .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
|
|
|
+ ])
|
|
|
+
|
|
|
+ if !inputUrlTextField.stringValue.isEmpty {
|
|
|
+ goButton.isHidden = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func isValidateEmail(_ email: String) -> Bool {
|
|
|
+ let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
|
|
|
+ let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
|
|
|
+ return emailTest.evaluate(with: email)
|
|
|
+ }
|
|
|
+
|
|
|
+ func judgeWebURL(_ urlString: String) -> String {
|
|
|
+ var updatedURL = urlString
|
|
|
+ if !updatedURL.hasPrefix("http://") && !updatedURL.hasPrefix("https://") {
|
|
|
+ updatedURL = "https://" + updatedURL
|
|
|
+ }
|
|
|
+ if updatedURL == "https://" {
|
|
|
+ updatedURL = ""
|
|
|
+ }
|
|
|
+ return updatedURL
|
|
|
+ }
|
|
|
+
|
|
|
+ func judgeEmailURL(_ urlString: String) -> String {
|
|
|
+ var updatedURL = urlString
|
|
|
+ if !updatedURL.hasPrefix("mailto:") {
|
|
|
+ updatedURL = "mailto:" + updatedURL
|
|
|
+ }
|
|
|
+ if updatedURL == "mailto:" {
|
|
|
+ updatedURL = ""
|
|
|
+ }
|
|
|
+ return updatedURL
|
|
|
+ }
|
|
|
+
|
|
|
+ func annotationLinkSelectBox(_ box: KMBox) {
|
|
|
+ if box.isEqual(self.linkPageBox) {
|
|
|
+ self.linkPageBox.fillColor = NSColor.white
|
|
|
+ self.linkEmailBox.fillColor = NSColor.clear
|
|
|
+ self.linkUrlBox.fillColor = NSColor.clear
|
|
|
+ self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageSel")
|
|
|
+ self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlNor")
|
|
|
+ self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailNor")
|
|
|
+ let dexPage = Int(self.pageRecord) ?? 0
|
|
|
+ if self.pageRecord.count < 1 {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if dexPage < 1 || dexPage > self.pageCount {
|
|
|
+ self.errorLabel.isHidden = false
|
|
|
+ } else {
|
|
|
+ self.errorLabel.isHidden = true
|
|
|
+ }
|
|
|
+ } else if box.isEqual(self.linkUrlBox) {
|
|
|
+ self.linkUrlBox.fillColor = NSColor.white
|
|
|
+ self.linkEmailBox.fillColor = NSColor.clear
|
|
|
+ self.linkPageBox.fillColor = NSColor.clear
|
|
|
+ self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageNor")
|
|
|
+ self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlSel")
|
|
|
+ self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailNor")
|
|
|
+ self.errorLabel.isHidden = true
|
|
|
+ } else if box.isEqual(self.linkEmailBox) {
|
|
|
+ self.linkEmailBox.fillColor = NSColor.white
|
|
|
+ self.linkUrlBox.fillColor = NSColor.clear
|
|
|
+ self.linkPageBox.fillColor = NSColor.clear
|
|
|
+ self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageNor")
|
|
|
+ self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlNor")
|
|
|
+ self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailSel")
|
|
|
+ self.errorLabel.isHidden = true
|
|
|
+ }
|
|
|
+
|
|
|
+ self.updateInputUrlBoxState()
|
|
|
+ }
|
|
|
+
|
|
|
+ func updateInputUrlBoxState() {
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ if !self.errorLabel.isHidden {
|
|
|
+ self.inputUrlBox.borderColor = self.boxErrorBorderColor
|
|
|
+ } else {
|
|
|
+ self.inputUrlBox.borderColor = self.boxNormalBorderColor
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func updateTargetBoxState(state: KMAnnotationLinkState) {
|
|
|
+ self.targetButtonState = state
|
|
|
+ if Thread.isMainThread {
|
|
|
+ if state == .Normal {
|
|
|
+ self.tagrgetBox.borderColor = self.boxNormalBorderColor
|
|
|
+ } else if state == .Hover {
|
|
|
+ self.tagrgetBox.borderColor = NSColor(red: 104/255.0, green: 172/255.0, blue: 248/255.0, alpha: 1.0)
|
|
|
+ } else if state == .Selected {
|
|
|
+ self.tagrgetBox.borderColor = NSColor(red: 23/255.0, green: 112/255.0, blue: 244/255.0, alpha: 1.0)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ if state == .Normal {
|
|
|
+ self.tagrgetBox.borderColor = self.boxNormalBorderColor
|
|
|
+ } else if state == .Hover {
|
|
|
+ self.tagrgetBox.borderColor = NSColor(red: 104/255.0, green: 172/255.0, blue: 248/255.0, alpha: 1.0)
|
|
|
+ } else if state == .Selected {
|
|
|
+ self.tagrgetBox.borderColor = NSColor(red: 23/255.0, green: 112/255.0, blue: 244/255.0, alpha: 1.0)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func dealThumibleImage(dexPage: UInt) {
|
|
|
+ if dexPage > 0 && dexPage <= self.pageCount && self.pageRecord.count > 0 {
|
|
|
+ self.pageImageThumible.isHidden = false
|
|
|
+ self.goButton.isHidden = false
|
|
|
+ let goPage = Int(self.inputUrlTextField.stringValue)! - 1
|
|
|
+ if let page = self.pdfview?.document.page(at: UInt(goPage)) {
|
|
|
+ self.pageImageThumible.image = page.thumbnail(of: page.bounds(for: .mediaBox).size)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ self.pageImageThumible.isHidden = true
|
|
|
+ self.goButton.isHidden = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //MARK: Action
|
|
|
+
|
|
|
+ @IBAction func goButtonAction(_ sender: NSButton) {
|
|
|
+ switch self.linkType {
|
|
|
+ case .Page:
|
|
|
+ if let linkAnnotation = self.pdfview?.activeAnnotation as? CPDFLinkAnnotation {
|
|
|
+ linkAnnotation.setURL(nil)
|
|
|
+
|
|
|
+ var dexPage: UInt = 0
|
|
|
+ if self.isGo {
|
|
|
+ self.isGo = false
|
|
|
+ self.startPage = "\(self.pdfview!.currentPageIndex + 1)"
|
|
|
+ if let goPageIndex = UInt(inputUrlTextField.stringValue) {
|
|
|
+ dexPage = goPageIndex
|
|
|
+ }
|
|
|
+
|
|
|
+ goButton.title = NSLocalizedString("Go Back", comment: "")
|
|
|
+ goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
|
|
|
+ .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
|
|
|
+ ])
|
|
|
+ } else {
|
|
|
+ self.isGo = true
|
|
|
+ if let startPageIndex = UInt(self.startPage) {
|
|
|
+ dexPage = startPageIndex
|
|
|
+ }
|
|
|
+
|
|
|
+ self.goButton.title = NSLocalizedString("Go", comment: "")
|
|
|
+ self.goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
|
|
|
+ .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
|
|
|
+ ])
|
|
|
+ }
|
|
|
+
|
|
|
+ if dexPage < 1 || dexPage > self.pageCount {
|
|
|
+ let alert = NSAlert()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
|
|
|
+ alert.runModal()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if let goPageIndex = UInt(self.inputUrlTextField.stringValue),
|
|
|
+ let destination = self.targetDestination ?? CPDFDestination(document: self.pdfview!.document, pageIndex: Int(goPageIndex) - 1) {
|
|
|
+ linkAnnotation.setDestination(destination)
|
|
|
+ self.pdfview!.setNeedsDisplay(self.annotation)
|
|
|
+
|
|
|
+ if self.isGo, let startDest = self.startDestination {
|
|
|
+ self.pdfview!.go(to: startDest)
|
|
|
+ return
|
|
|
+ } else if let targetDest = targetDestination {
|
|
|
+ self.pdfview!.go(to: targetDest)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if let dest = CPDFDestination(document: self.pdfview!.document, pageIndex: Int(dexPage) - 1) {
|
|
|
+ self.pdfview!.go(toPageIndex: dest.pageIndex, animated: true)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ self.updateTargetBoxState(state: .Selected)
|
|
|
+ self.pdfview!.isSetLinkDestinationArea = true
|
|
|
+
|
|
|
+ case .URL:
|
|
|
+ if let linkAnnotation = self.pdfview!.activeAnnotation as? CPDFLinkAnnotation {
|
|
|
+ linkAnnotation.setDestination(nil)
|
|
|
+ let linkUrlPath = self.judgeWebURL(inputUrlTextField.stringValue)
|
|
|
+ linkAnnotation.setURL(linkUrlPath)
|
|
|
+ self.pdfview!.setNeedsDisplay(self.annotation)
|
|
|
+
|
|
|
+ if let url = URL(string: linkAnnotation.url() ?? "") {
|
|
|
+ NSWorkspace.shared.open(url)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case .Email:
|
|
|
+ if let linkAnnotation = self.pdfview?.activeAnnotation as? CPDFLinkAnnotation {
|
|
|
+ linkAnnotation.setDestination(nil)
|
|
|
+
|
|
|
+ if !isValidateEmail(inputUrlTextField.stringValue) {
|
|
|
+ let alert = NSAlert()
|
|
|
+ alert.alertStyle = .critical
|
|
|
+ alert.messageText = NSLocalizedString("Invalid email address. Please enter a valid email address.", comment: "")
|
|
|
+ alert.runModal()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let linkUrlPath = self.judgeEmailURL(self.inputUrlTextField.stringValue)
|
|
|
+ linkAnnotation.setURL(linkUrlPath)
|
|
|
+ self.pdfview!.setNeedsDisplay(self.annotation)
|
|
|
+
|
|
|
+ if let url = URL(string: linkAnnotation.url() ?? "") {
|
|
|
+ NSWorkspace.shared.open(url)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+extension KMAnnotationLinkViewController: NSTextFieldDelegate {
|
|
|
+ @objc func controlTextDidChange(_ obj: Notification) {
|
|
|
+ guard let textField = obj.object as? NSTextField else {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ self.errorLabel.isHidden = true
|
|
|
+ if self.mouseDownBox == self.linkPageBox {
|
|
|
+ self.pageRecord = textField.stringValue
|
|
|
+ } else if self.mouseDownBox == self.linkUrlBox {
|
|
|
+ self.urlRecord = textField.stringValue
|
|
|
+ } else if mouseDownBox == linkEmailBox {
|
|
|
+ self.emailRecord = textField.stringValue
|
|
|
+ }
|
|
|
+
|
|
|
+ if self.linkType == .Page {
|
|
|
+ (self.pdfview?.activeAnnotation as! CPDFLinkAnnotation as CPDFLinkAnnotation).setURL(nil)
|
|
|
+ let dexPage = Int(self.inputUrlTextField.stringValue) ?? 1
|
|
|
+ if (dexPage < 1 || dexPage > self.pageCount) && self.pageRecord.count > 0 {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
|
|
|
+ self.errorLabel.isHidden = false
|
|
|
+ self.dealThumibleImage(dexPage: UInt(dexPage))
|
|
|
+ self.updateInputUrlBoxState()
|
|
|
+ return
|
|
|
+ } else if self.pageRecord.count > 0 {
|
|
|
+ self.errorLabel.isHidden = true
|
|
|
+ }
|
|
|
+ let page: CPDFPage = (self.pdfview?.document.page(at: UInt(dexPage - 1)))!
|
|
|
+ let destination: CPDFDestination = CPDFDestination(document: self.pdfview!.document, pageIndex: dexPage - 1, at: CGPoint(x: 0, y: page.bounds.size.height), zoom: self.pdfview!.scaleFactor)
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(destination)
|
|
|
+ self.pdfview?.setNeedsDisplayAnnotationViewFor(self.pdfview?.activeAnnotation.page)
|
|
|
+
|
|
|
+ // 显示预览图
|
|
|
+ self.dealThumibleImage(dexPage: UInt(dexPage))
|
|
|
+ self.updateInputUrlBoxState()
|
|
|
+ } else if self.linkType == .URL {
|
|
|
+ (pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
|
|
|
+ let linkUrlPath: String = self.urlRecord
|
|
|
+ if linkUrlPath == "" {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(nil)
|
|
|
+ } else {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(linkUrlPath)
|
|
|
+ }
|
|
|
+ self.pdfview?.setNeedsDisplayAnnotationViewFor(self.pdfview?.activeAnnotation.page)
|
|
|
+ } else if self.linkType == .Email {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
|
|
|
+ let linkUrlPath = self.judgeEmailURL(self.emailRecord)
|
|
|
+ if linkUrlPath == "" {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(nil)
|
|
|
+ } else {
|
|
|
+ (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(linkUrlPath)
|
|
|
+ }
|
|
|
+ self.pdfview?.setNeedsDisplayAnnotationViewFor(pdfview?.activeAnnotation.page)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
|
|
|
+ if commandSelector == #selector(insertNewline(_:)) {
|
|
|
+ self.view.window?.makeFirstResponder(self.pdfview)
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ override func mouseDown(with event: NSEvent) {
|
|
|
+ super.mouseDown(with: event)
|
|
|
+
|
|
|
+ self.view.window?.makeFirstResponder(self.pdfview)
|
|
|
+ }
|
|
|
+}
|