KMAnnotationLinkViewController.swift 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. //
  2. // KMAnnotationLinkViewController.swift
  3. // PDF Master
  4. //
  5. // Created by wanjun on 2023/10/11.
  6. //
  7. import Cocoa
  8. let URLPlaceholder = "https://www.pdfreaderpro.com"
  9. let EmailPlaceholder = "support@pdfreaderpro.com"
  10. enum KMAnnotationLinkType: Int {
  11. case Page
  12. case URL
  13. case Email
  14. }
  15. enum KMAnnotationLinkState: Int {
  16. case Normal
  17. case Hover
  18. case Selected
  19. }
  20. class KMAnnotationLinkViewController: KMAnnotationPropertyBaseController {
  21. var annotationModel: CPDFAnnotationModel?
  22. var _content: String = ""
  23. var pageCount: Int = 0
  24. var _isCreateLink: Bool = false
  25. @IBOutlet weak var linkStyleView: NSView!
  26. @IBOutlet var linkPageBox: KMBox!
  27. @IBOutlet var linkPageImageView: NSImageView!
  28. @IBOutlet weak var pageImageThumible: NSImageView!
  29. @IBOutlet weak var targetButton: KMCoverButton!
  30. @IBOutlet weak var targetLabel: NSTextField!
  31. @IBOutlet weak var tagrgetBox: NSBox!
  32. @IBOutlet var linkUrlBox: KMBox!
  33. @IBOutlet var linkUrlImageView: NSImageView!
  34. @IBOutlet var linkEmailBox: KMBox!
  35. @IBOutlet var linkEmailImageView: NSImageView!
  36. @IBOutlet var contentBox: NSBox!
  37. @IBOutlet var urlView: NSView!
  38. @IBOutlet var urlLabel: NSTextField!
  39. @IBOutlet var inputUrlTextField: NSTextField!
  40. @IBOutlet weak var inputUrlBox: NSBox!
  41. @IBOutlet var goButton: NSButton!
  42. @IBOutlet var errorLabel: NSTextField!
  43. @IBOutlet weak var goButtonTopComstraint: NSLayoutConstraint!
  44. var annotation: CPDFLinkAnnotation?
  45. var _linkType: KMAnnotationLinkType = .Page
  46. var mouseDownBox: KMBox?
  47. var pageRecord: String = ""
  48. var urlRecord: String = ""
  49. var emailRecord: String = ""
  50. var startPage: String = ""
  51. var isGo: Bool = false
  52. var boxNormalBorderColor: NSColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1)
  53. var boxErrorBorderColor: NSColor = NSColor(red: 243/255.0, green: 70/255.0, blue: 91/255.0, alpha: 1)
  54. var targetButtonState: KMAnnotationLinkState = .Normal
  55. //MARK: Init Methods
  56. override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
  57. super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
  58. self.boxNormalBorderColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1)
  59. self.boxErrorBorderColor = NSColor(red: 243/255.0, green: 70/255.0, blue: 91/255.0, alpha: 1)
  60. }
  61. required init?(coder: NSCoder) {
  62. super.init(coder: coder)
  63. }
  64. deinit {
  65. NotificationCenter.default.removeObserver(self)
  66. inputUrlTextField.delegate = nil
  67. print("\(#function)")
  68. }
  69. //MARK: View Methods
  70. override func viewDidLoad() {
  71. super.viewDidLoad()
  72. // Do view setup here.
  73. self.annotation = self.annotationModel?.annotation as? CPDFLinkAnnotation
  74. self.pageRecord = ""
  75. self.urlRecord = ""
  76. self.emailRecord = ""
  77. self.linkStyleView.wantsLayer = true
  78. self.linkPageImageView.wantsLayer = true
  79. self.linkUrlImageView.wantsLayer = true
  80. self.linkEmailImageView.wantsLayer = true
  81. self.linkStyleView.layer?.backgroundColor = NSColor(red: 223.0/255.0, green: 225.0/255.0, blue: 229.0/255.0, alpha: 1.0).cgColor
  82. self.linkStyleView.layer?.cornerRadius = 6.0
  83. self.linkStyleView.layer?.masksToBounds = true
  84. let boxArr: [KMBox] = [linkPageBox, linkUrlBox, linkEmailBox]
  85. for box in boxArr {
  86. box.downCallback = { [weak self] downEntered, mouseBox, event in
  87. guard let self = self else { return }
  88. if downEntered {
  89. if self.mouseDownBox === mouseBox {
  90. return
  91. }
  92. var mouseDownInt = 0
  93. if self.linkPageBox === mouseBox {
  94. self.inputUrlTextField.stringValue = ""
  95. self.linkType = .Page
  96. mouseDownInt = 0
  97. } else if self.linkUrlBox === mouseBox {
  98. self.inputUrlTextField.stringValue = ""
  99. self.linkType = .URL
  100. mouseDownInt = 1
  101. } else if self.linkEmailBox === mouseBox {
  102. self.inputUrlTextField.stringValue = ""
  103. self.linkType = .Email
  104. mouseDownInt = 2
  105. }
  106. UserDefaults.standard.set(mouseDownInt, forKey: "kmLinkSelectIndex")
  107. UserDefaults.standard.synchronize()
  108. self.mouseDownBox = mouseBox
  109. }
  110. }
  111. }
  112. self.isGo = true
  113. self.targetLabel.stringValue = NSLocalizedString("Locate the target page", tableName: "MainMenu", comment: "")
  114. self.inputUrlTextField.wantsLayer = true
  115. self.inputUrlTextField.focusRingType = .none
  116. self.linkPageImageView.layer?.cornerRadius = 4.0
  117. self.linkUrlImageView.layer?.cornerRadius = 4.0
  118. self.linkEmailImageView.layer?.cornerRadius = 4.0
  119. let inputUrlTextFieldCell = self.inputUrlTextField.cell as! NSTextFieldCell
  120. inputUrlTextFieldCell.allowedInputSourceLocales = [NSAllRomanInputSourcesLocaleIdentifier]
  121. if self.linkType == .Email {
  122. self.linkType = .Email
  123. self.mouseDownBox = linkEmailBox
  124. } else if linkType == .URL {
  125. self.linkType = .URL
  126. self.mouseDownBox = linkUrlBox
  127. } else if linkType == .Page {
  128. self.linkType = .Page
  129. self.mouseDownBox = linkPageBox
  130. }
  131. self.targetButton.coverAction = { [weak self] button, action in
  132. guard let self = self, self.targetButtonState != .Selected else {
  133. return
  134. }
  135. if action == .enter {
  136. self.updateTargetBoxState(state: .Hover)
  137. } else if action == .exit {
  138. self.updateTargetBoxState(state: .Normal)
  139. }
  140. }
  141. NSEvent.addLocalMonitorForEvents(matching: .keyDown) { [weak self] event in
  142. guard let self = self else { return event }
  143. if event.keyCode == 53 {
  144. if self.inputUrlTextField.isEditable {
  145. self.pdfview?.annotationType = .unkown
  146. }
  147. }
  148. return event
  149. }
  150. }
  151. override func viewDidAppear() {
  152. super.viewDidAppear()
  153. self.inputUrlTextField.delegate = self
  154. }
  155. override func setupUI() {
  156. super.setupUI()
  157. let fontName = "SFProText-Regular"
  158. self.urlLabel.font = NSFont(name: fontName, size: 12)
  159. self.urlLabel.textColor = NSColor(red: 97.0/255.0, green: 100.0/255.0, blue: 105.0/255.0, alpha: 1)
  160. self.inputUrlBox.borderColor = self.boxNormalBorderColor
  161. self.inputUrlBox.fillColor = NSColor.white
  162. self.errorLabel.textColor = self.boxErrorBorderColor
  163. self.errorLabel.font = NSFont(name: fontName, size: 12)
  164. self.tagrgetBox.fillColor = NSColor.white
  165. self.updateTargetBoxState(state: .Normal)
  166. self.targetLabel.font = NSFont(name: fontName, size: 14)
  167. self.targetLabel.textColor = NSColor(red: 37/255.0, green: 38/255.0, blue: 41/255.0, alpha: 1)
  168. self.goButton.title = NSLocalizedString("Go", comment: "")
  169. 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)])
  170. }
  171. //MARK: Set、Get
  172. var linkType: KMAnnotationLinkType {
  173. get {
  174. return _linkType
  175. }
  176. set {
  177. _linkType = newValue
  178. switch _linkType {
  179. case .Page:
  180. self.createLinkPageView()
  181. self.inputUrlTextField.becomeFirstResponder()
  182. case .URL:
  183. self.createLinkURLView()
  184. self.inputUrlTextField.becomeFirstResponder()
  185. case .Email:
  186. self.createLinkEmailView()
  187. self.inputUrlTextField.becomeFirstResponder()
  188. default:
  189. break
  190. }
  191. }
  192. }
  193. var content: String {
  194. get {
  195. return _content
  196. }
  197. set {
  198. _content = newValue
  199. if _content != "" {
  200. if _content.count > 0 {
  201. let typeLocal = _content.first ?? Character("\0")
  202. if typeLocal == "0" {
  203. _content = (_content as NSString).substring(from: 1)
  204. self.linkType = .Page
  205. self.inputUrlTextField.stringValue = _content
  206. self.mouseDownBox = self.linkPageBox
  207. } else {
  208. if content.dropFirst().hasPrefix("mailto:") {
  209. _content = (_content as NSString).substring(from: 8)
  210. self.linkType = .Email
  211. self.mouseDownBox = self.linkEmailBox
  212. } else {
  213. _content = (_content as NSString).substring(from: 1)
  214. self.linkType = .URL
  215. self.mouseDownBox = self.linkUrlBox
  216. }
  217. }
  218. }
  219. } else {
  220. _content = "http://"
  221. self.linkType = .URL
  222. self.mouseDownBox = self.linkUrlBox
  223. }
  224. }
  225. }
  226. override var pdfview: CPDFListView? {
  227. get {
  228. return _pdfview
  229. }
  230. set {
  231. _pdfview = newValue
  232. self.startPage = String(format: "%ld", _pdfview!.currentPageIndex+1)
  233. }
  234. }
  235. var isCreateLink: Bool {
  236. get {
  237. return _isCreateLink
  238. }
  239. set {
  240. _isCreateLink = newValue
  241. if _isCreateLink {
  242. self.linkType = .Page
  243. self.mouseDownBox = self.linkPageBox
  244. }
  245. }
  246. }
  247. //MARK: private
  248. func createLinkPageView() {
  249. self.annotationLinkSelectBox(self.linkPageBox)
  250. self.urlLabel.stringValue = NSLocalizedString("Page", comment: "")
  251. self.inputUrlTextField.formatter = TextFieldFormatter()
  252. if self.pdfview!.document?.pageCount ?? 0 > 1 {
  253. self.inputUrlTextField.placeholderString = NSLocalizedString("Enter target page", comment: "")
  254. } else {
  255. self.inputUrlTextField.placeholderString = "1"
  256. }
  257. if let destination = self.annotation!.destination() {
  258. let pageIndex = destination.pageIndex
  259. self.inputUrlTextField.stringValue = "\(pageIndex + 1)"
  260. self.pageRecord = "\(pageIndex + 1)"
  261. } else {
  262. self.pageRecord = "1"
  263. }
  264. if self.inputUrlTextField.stringValue.count == 0 {
  265. self.inputUrlTextField.stringValue = self.pageRecord
  266. }
  267. self.tagrgetBox.isHidden = false
  268. self.pageImageThumible.isHidden = true
  269. self.goButton.isHidden = true
  270. self.goButtonTopComstraint.constant = 20
  271. self.errorLabel.stringValue = NSLocalizedString("Page number out of range", comment: "")
  272. if self.inputUrlTextField.stringValue.count == 0 {
  273. } else {
  274. if let dexPage = Int(self.inputUrlTextField.stringValue) {
  275. self.dealThumibleImage(dexPage: UInt(dexPage))
  276. }
  277. }
  278. }
  279. func createLinkURLView() {
  280. self.annotationLinkSelectBox(self.linkUrlBox)
  281. self.urlLabel.stringValue = NSLocalizedString("URL:", comment: "")
  282. self.inputUrlTextField.formatter = nil
  283. self.inputUrlTextField.placeholderString = "https://www.pdfreaderpro.com"
  284. if let urlString = self.annotation?.url() {
  285. var modifiedURL = urlString
  286. if modifiedURL.hasPrefix("http://") {
  287. modifiedURL = (modifiedURL as NSString).substring(from: 7)
  288. } else if modifiedURL.hasPrefix("https://://") {
  289. modifiedURL = (modifiedURL as NSString).substring(from: 8)
  290. }
  291. self.inputUrlTextField.stringValue = modifiedURL
  292. self.urlRecord = modifiedURL
  293. }
  294. if self.inputUrlTextField.stringValue.count == 0 {
  295. self.inputUrlTextField.stringValue = self.urlRecord
  296. }
  297. self.tagrgetBox.isHidden = true
  298. self.pageImageThumible.isHidden = true
  299. self.goButton.isHidden = true
  300. self.goButtonTopComstraint.constant = -390
  301. self.errorLabel.stringValue = NSLocalizedString("Invalid Email. Please re-enter correct email.", comment: "")
  302. self.goButton.title = NSLocalizedString("Go", comment: "")
  303. 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)])
  304. if self.inputUrlTextField.stringValue.count > 0 {
  305. self.goButton.isHidden = false
  306. }
  307. }
  308. func createLinkEmailView() {
  309. self.annotationLinkSelectBox(self.linkEmailBox)
  310. self.urlLabel.stringValue = NSLocalizedString("Email:", comment: "")
  311. self.inputUrlTextField.formatter = nil
  312. self.inputUrlTextField.placeholderString = "support@pdfreaderpro.com"
  313. if let urlString = annotation?.url(), urlString.contains("mailto") {
  314. if urlString.hasPrefix("mailto:") {
  315. let email = String(urlString.suffix(from: urlString.index(urlString.startIndex, offsetBy: 7)))
  316. inputUrlTextField.stringValue = email
  317. emailRecord = email
  318. }
  319. if inputUrlTextField.stringValue.isEmpty {
  320. inputUrlTextField.stringValue = emailRecord
  321. }
  322. }
  323. tagrgetBox.isHidden = true
  324. pageImageThumible.isHidden = true
  325. goButton.isHidden = true
  326. goButtonTopComstraint.constant = -390
  327. errorLabel.stringValue = NSLocalizedString("Invalid Email. Please re-enter correct email.", comment: "")
  328. goButton.title = NSLocalizedString("Go", comment: "")
  329. goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
  330. .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
  331. ])
  332. if !inputUrlTextField.stringValue.isEmpty {
  333. goButton.isHidden = false
  334. }
  335. }
  336. func isValidateEmail(_ email: String) -> Bool {
  337. let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
  338. let emailTest = NSPredicate(format: "SELF MATCHES %@", emailRegex)
  339. return emailTest.evaluate(with: email)
  340. }
  341. func judgeWebURL(_ urlString: String) -> String {
  342. var updatedURL = urlString
  343. if !updatedURL.hasPrefix("http://") && !updatedURL.hasPrefix("https://") {
  344. updatedURL = "https://" + updatedURL
  345. }
  346. if updatedURL == "https://" {
  347. updatedURL = ""
  348. }
  349. return updatedURL
  350. }
  351. func judgeEmailURL(_ urlString: String) -> String {
  352. var updatedURL = urlString
  353. if !updatedURL.hasPrefix("mailto:") {
  354. updatedURL = "mailto:" + updatedURL
  355. }
  356. if updatedURL == "mailto:" {
  357. updatedURL = ""
  358. }
  359. return updatedURL
  360. }
  361. func annotationLinkSelectBox(_ box: KMBox) {
  362. if box.isEqual(self.linkPageBox) {
  363. self.linkPageBox.fillColor = NSColor.white
  364. self.linkEmailBox.fillColor = NSColor.clear
  365. self.linkUrlBox.fillColor = NSColor.clear
  366. self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageSel")
  367. self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlNor")
  368. self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailNor")
  369. let dexPage = Int(self.pageRecord) ?? 0
  370. if self.pageRecord.count < 1 {
  371. return
  372. }
  373. if dexPage < 1 || dexPage > self.pageCount {
  374. self.errorLabel.isHidden = false
  375. } else {
  376. self.errorLabel.isHidden = true
  377. }
  378. } else if box.isEqual(self.linkUrlBox) {
  379. self.linkUrlBox.fillColor = NSColor.white
  380. self.linkEmailBox.fillColor = NSColor.clear
  381. self.linkPageBox.fillColor = NSColor.clear
  382. self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageNor")
  383. self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlSel")
  384. self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailNor")
  385. self.errorLabel.isHidden = true
  386. } else if box.isEqual(self.linkEmailBox) {
  387. self.linkEmailBox.fillColor = NSColor.white
  388. self.linkUrlBox.fillColor = NSColor.clear
  389. self.linkPageBox.fillColor = NSColor.clear
  390. self.linkPageImageView.image = NSImage(named: "KMImageNamePropertybarLinkPageNor")
  391. self.linkUrlImageView.image = NSImage(named: "KMImageNamePropertybarLinkUrlNor")
  392. self.linkEmailImageView.image = NSImage(named: "KMImageNamePropertybarLinkEmailSel")
  393. self.errorLabel.isHidden = true
  394. }
  395. self.updateInputUrlBoxState()
  396. }
  397. func updateInputUrlBoxState() {
  398. DispatchQueue.main.async {
  399. if !self.errorLabel.isHidden {
  400. self.inputUrlBox.borderColor = self.boxErrorBorderColor
  401. } else {
  402. self.inputUrlBox.borderColor = self.boxNormalBorderColor
  403. }
  404. }
  405. }
  406. func updateTargetBoxState(state: KMAnnotationLinkState) {
  407. self.targetButtonState = state
  408. if Thread.isMainThread {
  409. if state == .Normal {
  410. self.tagrgetBox.borderColor = self.boxNormalBorderColor
  411. } else if state == .Hover {
  412. self.tagrgetBox.borderColor = NSColor(red: 104/255.0, green: 172/255.0, blue: 248/255.0, alpha: 1.0)
  413. } else if state == .Selected {
  414. self.tagrgetBox.borderColor = NSColor(red: 23/255.0, green: 112/255.0, blue: 244/255.0, alpha: 1.0)
  415. }
  416. } else {
  417. DispatchQueue.main.async {
  418. if state == .Normal {
  419. self.tagrgetBox.borderColor = self.boxNormalBorderColor
  420. } else if state == .Hover {
  421. self.tagrgetBox.borderColor = NSColor(red: 104/255.0, green: 172/255.0, blue: 248/255.0, alpha: 1.0)
  422. } else if state == .Selected {
  423. self.tagrgetBox.borderColor = NSColor(red: 23/255.0, green: 112/255.0, blue: 244/255.0, alpha: 1.0)
  424. }
  425. }
  426. }
  427. }
  428. func dealThumibleImage(dexPage: UInt) {
  429. if dexPage > 0 && dexPage <= self.pageCount && self.pageRecord.count > 0 {
  430. self.pageImageThumible.isHidden = false
  431. self.goButton.isHidden = false
  432. let goPage = Int(self.inputUrlTextField.stringValue)! - 1
  433. if let page = self.pdfview?.document.page(at: UInt(goPage)) {
  434. self.pageImageThumible.image = page.thumbnail(of: page.bounds(for: .mediaBox).size)
  435. }
  436. } else {
  437. self.pageImageThumible.isHidden = true
  438. self.goButton.isHidden = true
  439. }
  440. }
  441. //MARK: Action
  442. @IBAction func goButtonAction(_ sender: NSButton) {
  443. switch self.linkType {
  444. case .Page:
  445. if let linkAnnotation = self.pdfview?.activeAnnotation as? CPDFLinkAnnotation {
  446. linkAnnotation.setURL(nil)
  447. var dexPage: UInt = 0
  448. if self.isGo {
  449. self.isGo = false
  450. self.startPage = "\(self.pdfview!.currentPageIndex + 1)"
  451. if let goPageIndex = UInt(inputUrlTextField.stringValue) {
  452. dexPage = goPageIndex
  453. }
  454. goButton.title = NSLocalizedString("Go Back", comment: "")
  455. goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
  456. .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
  457. ])
  458. } else {
  459. self.isGo = true
  460. if let startPageIndex = UInt(self.startPage) {
  461. dexPage = startPageIndex
  462. }
  463. self.goButton.title = NSLocalizedString("Go", comment: "")
  464. self.goButton.attributedTitle = NSAttributedString(string: goButton.title, attributes: [
  465. .foregroundColor: NSColor(red: 23.0/255.0, green: 112.0/255.0, blue: 244.0/255.0, alpha: 1)
  466. ])
  467. }
  468. if dexPage < 1 || dexPage > self.pageCount {
  469. let alert = NSAlert()
  470. alert.alertStyle = .critical
  471. alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
  472. alert.runModal()
  473. return
  474. }
  475. if let goPageIndex = UInt(self.inputUrlTextField.stringValue),
  476. let destination = self.targetDestination ?? CPDFDestination(document: self.pdfview!.document, pageIndex: Int(goPageIndex) - 1) {
  477. linkAnnotation.setDestination(destination)
  478. self.pdfview!.setNeedsDisplay(self.annotation)
  479. if self.isGo, let startDest = self.startDestination {
  480. self.pdfview!.go(to: startDest)
  481. return
  482. } else if let targetDest = targetDestination {
  483. self.pdfview!.go(to: targetDest)
  484. return
  485. }
  486. if let dest = CPDFDestination(document: self.pdfview!.document, pageIndex: Int(dexPage) - 1) {
  487. self.pdfview!.go(toPageIndex: dest.pageIndex, animated: true)
  488. }
  489. }
  490. }
  491. self.updateTargetBoxState(state: .Selected)
  492. self.pdfview!.isSetLinkDestinationArea = true
  493. case .URL:
  494. if let linkAnnotation = self.pdfview!.activeAnnotation as? CPDFLinkAnnotation {
  495. linkAnnotation.setDestination(nil)
  496. let linkUrlPath = self.judgeWebURL(inputUrlTextField.stringValue)
  497. linkAnnotation.setURL(linkUrlPath)
  498. self.pdfview!.setNeedsDisplay(self.annotation)
  499. if let url = URL(string: linkAnnotation.url() ?? "") {
  500. NSWorkspace.shared.open(url)
  501. }
  502. }
  503. case .Email:
  504. if let linkAnnotation = self.pdfview?.activeAnnotation as? CPDFLinkAnnotation {
  505. linkAnnotation.setDestination(nil)
  506. if !isValidateEmail(inputUrlTextField.stringValue) {
  507. let alert = NSAlert()
  508. alert.alertStyle = .critical
  509. alert.messageText = NSLocalizedString("Invalid email address. Please enter a valid email address.", comment: "")
  510. alert.runModal()
  511. return
  512. }
  513. let linkUrlPath = self.judgeEmailURL(self.inputUrlTextField.stringValue)
  514. linkAnnotation.setURL(linkUrlPath)
  515. self.pdfview!.setNeedsDisplay(self.annotation)
  516. if let url = URL(string: linkAnnotation.url() ?? "") {
  517. NSWorkspace.shared.open(url)
  518. }
  519. }
  520. default:
  521. break
  522. }
  523. }
  524. }
  525. extension KMAnnotationLinkViewController: NSTextFieldDelegate {
  526. @objc func controlTextDidChange(_ obj: Notification) {
  527. guard let textField = obj.object as? NSTextField else {
  528. return
  529. }
  530. self.errorLabel.isHidden = true
  531. if self.mouseDownBox == self.linkPageBox {
  532. self.pageRecord = textField.stringValue
  533. } else if self.mouseDownBox == self.linkUrlBox {
  534. self.urlRecord = textField.stringValue
  535. } else if mouseDownBox == linkEmailBox {
  536. self.emailRecord = textField.stringValue
  537. }
  538. if self.linkType == .Page {
  539. (self.pdfview?.activeAnnotation as! CPDFLinkAnnotation as CPDFLinkAnnotation).setURL(nil)
  540. let dexPage = Int(self.inputUrlTextField.stringValue) ?? 1
  541. if (dexPage < 1 || dexPage > self.pageCount) && self.pageRecord.count > 0 {
  542. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
  543. self.errorLabel.isHidden = false
  544. self.dealThumibleImage(dexPage: UInt(dexPage))
  545. self.updateInputUrlBoxState()
  546. return
  547. } else if self.pageRecord.count > 0 {
  548. self.errorLabel.isHidden = true
  549. }
  550. let page: CPDFPage = (self.pdfview?.document.page(at: UInt(dexPage - 1)))!
  551. let destination: CPDFDestination = CPDFDestination(document: self.pdfview!.document, pageIndex: dexPage - 1, at: CGPoint(x: 0, y: page.bounds.size.height), zoom: self.pdfview!.scaleFactor)
  552. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(destination)
  553. self.pdfview?.setNeedsDisplayAnnotationViewFor(self.pdfview?.activeAnnotation.page)
  554. // 显示预览图
  555. self.dealThumibleImage(dexPage: UInt(dexPage))
  556. self.updateInputUrlBoxState()
  557. } else if self.linkType == .URL {
  558. (pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
  559. let linkUrlPath: String = self.urlRecord
  560. if linkUrlPath == "" {
  561. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(nil)
  562. } else {
  563. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(linkUrlPath)
  564. }
  565. self.pdfview?.setNeedsDisplayAnnotationViewFor(self.pdfview?.activeAnnotation.page)
  566. } else if self.linkType == .Email {
  567. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setDestination(nil)
  568. let linkUrlPath = self.judgeEmailURL(self.emailRecord)
  569. if linkUrlPath == "" {
  570. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(nil)
  571. } else {
  572. (self.pdfview?.activeAnnotation as? CPDFLinkAnnotation)?.setURL(linkUrlPath)
  573. }
  574. self.pdfview?.setNeedsDisplayAnnotationViewFor(pdfview?.activeAnnotation.page)
  575. }
  576. }
  577. func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
  578. if commandSelector == #selector(insertNewline(_:)) {
  579. self.view.window?.makeFirstResponder(self.pdfview)
  580. return true
  581. }
  582. return false
  583. }
  584. override func mouseDown(with event: NSEvent) {
  585. super.mouseDown(with: event)
  586. self.view.window?.makeFirstResponder(self.pdfview)
  587. }
  588. }