KMLinkViewController.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. //
  2. // KMLinkViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by Niehaoyu on 2024/10/18.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. @objc public enum PDFLinkType: Int, CaseIterable{
  10. case Page = 0 //
  11. case Web //
  12. case Email //
  13. }
  14. @objc public enum PDFLinkPopupType: Int, CaseIterable{
  15. case None = 0 //默认类型
  16. case Page //
  17. case Web //
  18. case Email //
  19. case MultiSelect //Popup弹窗
  20. }
  21. /**
  22. 未选中注释:修改默认添加类型。
  23. 选中注释:
  24. - 切换类型:判断类型->修改显示信息。
  25. - 输入文字:修改跳转内容。
  26. */
  27. @objc protocol KMLinkViewControllerDelegate: AnyObject {
  28. @objc optional func kmLinkViewControllerDidUpdateMode(_ controller: KMLinkViewController)
  29. }
  30. //MARK: - KMLinkViewController
  31. @objcMembers class KMLinkViewController: KMNBaseViewController {
  32. @IBOutlet var contendBox: NSBox!
  33. @IBOutlet var infoContendView: NSView!
  34. @IBOutlet var tabsBGView: NSView!
  35. @IBOutlet var tabsView: ComponentTabs!
  36. @IBOutlet var typeContendView: NSView!
  37. @IBOutlet var linkPageView: KMLinkPageView!
  38. @IBOutlet var linkEmailView: KMLinkEmailView!
  39. @IBOutlet var linkWebView: KMLinkWebView!
  40. @IBOutlet var emptyContendView: ComponentEmpty!
  41. private weak var _pdfView: CPDFListView? = nil
  42. private var annotations: [CPDFLinkAnnotation] = []
  43. private var current_Annotation: CPDFLinkAnnotation? = nil
  44. var multiController: KMNAlignmentController = KMNAlignmentController.init() //注释多选界面
  45. let pageProperty = ComponentTabsProperty(tabsType: .underline_Fill, state: .normal, showIcon: false, title: KMLocalizedString("Page", comment: ""))
  46. let webProperty = ComponentTabsProperty(tabsType: .underline_Fill, state: .normal, showIcon: false, title: KMLocalizedString("Web", comment: ""))
  47. let emailProperty = ComponentTabsProperty(tabsType: .underline_Fill, state: .normal, showIcon: false, title: KMLocalizedString("Email", comment: ""))
  48. weak open var delegate: KMLinkViewControllerDelegate?
  49. public override func viewDidLoad() {
  50. super.viewDidLoad()
  51. // Do view setup here.
  52. setUpUI()
  53. }
  54. override func updateUILanguage() {
  55. super.updateUILanguage()
  56. }
  57. override func updateUIThemeColor() {
  58. super.updateUIThemeColor()
  59. contendBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/layout-middle")
  60. }
  61. func setUpUI() {
  62. tabsView.updateItemProperty([pageProperty, webProperty, emailProperty])
  63. tabsView.delegate = self
  64. linkPageView.delegate = self
  65. linkWebView.delegate = self
  66. linkEmailView.delegate = self
  67. multiController.delegate = self
  68. emptyContendView.properties = ComponentEmptyProperty(emptyType: .noLink,
  69. text: KMLocalizedString("Add Link"),
  70. subText: KMLocalizedString("Select an area or text on the page to add a link."))
  71. }
  72. //MARK: - Setter
  73. var pdfLinkType: PDFLinkType = .Page {
  74. didSet {
  75. view.window?.makeFirstResponder(nil)
  76. }
  77. }
  78. weak var pdfView: CPDFListView? {
  79. get {
  80. return _pdfView
  81. }
  82. set {
  83. _pdfView = newValue
  84. }
  85. }
  86. //MARK: - func
  87. public func reloadData() {
  88. guard let pdfView = self.pdfView else {
  89. return
  90. }
  91. typeContendView.isHidden = true
  92. emptyContendView.isHidden = true
  93. multiController.view.isHidden = true
  94. tabsBGView.isHidden = false
  95. let pdfAnnotations: [CPDFAnnotation] = pdfView.activeAnnotations as? [CPDFAnnotation] ?? []
  96. var linkAnnotations: [CPDFLinkAnnotation] = []
  97. for annotation in pdfAnnotations {
  98. if annotation is CPDFLinkAnnotation {
  99. linkAnnotations.append((annotation as! CPDFLinkAnnotation))
  100. }
  101. }
  102. annotations = linkAnnotations
  103. if annotations.count == 0 {
  104. emptyContendView.isHidden = false
  105. current_Annotation = nil
  106. linkPageView.clearData()
  107. linkWebView.clearData()
  108. linkEmailView.clearData()
  109. } else if annotations.count == 1 {
  110. if let annotation = annotations.first {
  111. if current_Annotation != annotation {
  112. current_Annotation = annotation
  113. linkPageView.clearData()
  114. linkWebView.clearData()
  115. linkEmailView.clearData()
  116. }
  117. }
  118. multiController.view.isHidden = true
  119. typeContendView.isHidden = false
  120. linkPageView.isHidden = true
  121. linkEmailView.isHidden = true
  122. linkWebView.isHidden = true
  123. if let url = current_Annotation?.url() {
  124. if url.hasPrefix("mailto:") {
  125. pdfLinkType = .Email
  126. } else {
  127. pdfLinkType = .Web
  128. }
  129. } else if let _ = current_Annotation?.destination() {
  130. pdfLinkType = .Page
  131. }
  132. if pdfLinkType == .Page {
  133. linkPageView.isHidden = false
  134. linkPageView.pdfView = pdfView
  135. linkPageView.annotation = current_Annotation
  136. linkPageView.reloadData()
  137. } else if pdfLinkType == .Web {
  138. linkWebView.isHidden = false
  139. linkWebView.annotation = current_Annotation
  140. } else if pdfLinkType == .Email {
  141. linkEmailView.isHidden = false
  142. linkEmailView.annotation = current_Annotation
  143. }
  144. } else {
  145. multiController.view.frame = CGRectMake((CGRectGetWidth(infoContendView.frame) - 232)/2, CGRectGetHeight(infoContendView.frame)-112, 232, 112)
  146. multiController.view.autoresizingMask = [.width, .minYMargin]
  147. infoContendView.addSubview(multiController.view)
  148. multiController.view.isHidden = false
  149. tabsBGView.isHidden = true
  150. if annotations.count > 2 {
  151. multiController.aligHorizontalXButton.properties.isDisabled = false
  152. multiController.aligVerticalYButton.properties.isDisabled = false
  153. } else {
  154. multiController.aligHorizontalXButton.properties.isDisabled = true
  155. multiController.aligVerticalYButton.properties.isDisabled = true
  156. }
  157. multiController.aligHorizontalXButton.reloadData()
  158. multiController.aligVerticalYButton.reloadData()
  159. }
  160. pageProperty.state = .normal
  161. webProperty.state = .normal
  162. emailProperty.state = .normal
  163. if pdfLinkType == .Page {
  164. pageProperty.state = .pressed
  165. } else if pdfLinkType == .Web {
  166. webProperty.state = .pressed
  167. } else if pdfLinkType == .Email {
  168. emailProperty.state = .pressed
  169. }
  170. tabsView.refreshItems()
  171. }
  172. func pdfLinkTypeChanged() {
  173. guard let _ = current_Annotation else {
  174. return
  175. }
  176. linkPageView.isHidden = true
  177. linkEmailView.isHidden = true
  178. linkWebView.isHidden = true
  179. if pdfLinkType == .Page {
  180. linkPageView.isHidden = false
  181. linkPageView.pdfView = pdfView
  182. linkPageView.annotation = current_Annotation
  183. linkPageView.reloadData()
  184. } else if pdfLinkType == .Web {
  185. linkWebView.isHidden = false
  186. linkWebView.annotation = current_Annotation
  187. } else if pdfLinkType == .Email {
  188. linkEmailView.isHidden = false
  189. linkEmailView.annotation = current_Annotation
  190. }
  191. }
  192. //MARK: - MouseEvent
  193. public override func mouseUp(with event: NSEvent) {
  194. super.mouseUp(with: event)
  195. }
  196. }
  197. //MARK: - ComponentTabsDelegate
  198. extension KMLinkViewController: ComponentTabsDelegate {
  199. public func componentTabsDidSelected(_ view: ComponentTabs, _ property: ComponentTabsProperty) {
  200. if KMMemberInfo.shared.isLogin == false && property != pageProperty{
  201. KMLoginWindowsController.shared.showWindow(nil)
  202. pdfLinkType = .Page
  203. pageProperty.state = .normal
  204. webProperty.state = .normal
  205. emailProperty.state = .normal
  206. if pdfLinkType == .Page {
  207. pageProperty.state = .pressed
  208. } else if pdfLinkType == .Web {
  209. webProperty.state = .pressed
  210. } else if pdfLinkType == .Email {
  211. emailProperty.state = .pressed
  212. }
  213. tabsView.refreshItems()
  214. pdfLinkTypeChanged()
  215. return
  216. }
  217. if let annotation = current_Annotation {
  218. if property == pageProperty {
  219. pdfLinkType = .Page
  220. annotation.setURL(nil)
  221. if linkPageView.choosedIndex > 0, let page = pdfView?.document.page(at: UInt(linkPageView.choosedIndex-1)) {
  222. let bounds = page.bounds(for: .cropBox)
  223. let destination = CPDFDestination(page: page, at: NSPoint(x: 0, y: bounds.size.height))
  224. annotation.setDestination(destination)
  225. }
  226. } else if property == webProperty {
  227. pdfLinkType = .Web
  228. annotation.setDestination(nil)
  229. let linkUrlPath = KMNTools.judgeWebURL(linkWebView.inputTextarea.properties.text)
  230. annotation.setURL(linkUrlPath)
  231. } else if property == emailProperty {
  232. pdfLinkType = .Email
  233. annotation.setDestination(nil)
  234. let linkUrlPath = KMNTools.judgeEmailURL(linkEmailView.inputTextarea.properties.text)
  235. annotation.setURL(linkUrlPath)
  236. }
  237. pdfLinkTypeChanged()
  238. }
  239. CPDFLinkAnnotation.updateDefault_AddLinkType(pdfLinkType.rawValue)
  240. delegate?.kmLinkViewControllerDidUpdateMode?(self)
  241. }
  242. }
  243. //MARK: - KMLinkPageViewDelegate
  244. extension KMLinkViewController: KMLinkPageViewDelegate {
  245. func kmLinkPageViewDidGoToPage(_ view: KMLinkPageView, _ pageIndex: Int) {
  246. if let _ = pdfView?.document.page(at: UInt(pageIndex-1)) {
  247. pdfView?.go(toPageIndex: pageIndex-1, animated: false)
  248. }
  249. }
  250. }
  251. //MARK: - KMLinkPageViewDelegate
  252. extension KMLinkViewController: KMLinkWebViewDelegate {
  253. func kmLinkWebViewDidGo(_ view: KMLinkWebView, _ webString: String) {
  254. guard let activeAnnotation = current_Annotation else {
  255. return
  256. }
  257. let linkUrlPath = KMNTools.judgeWebURL(webString)
  258. activeAnnotation.setURL(linkUrlPath)
  259. if let url = activeAnnotation.url() {
  260. if let data = URL(string: url) {
  261. NSWorkspace.shared.open(data)
  262. } else {
  263. let alert = NSAlert()
  264. alert.alertStyle = .critical
  265. alert.messageText = KMLocalizedString("Invalid URL. Please try again.", comment: "")
  266. alert.runModal()
  267. }
  268. } else {
  269. let alert = NSAlert()
  270. alert.alertStyle = .critical
  271. alert.messageText = KMLocalizedString("Invalid URL. Please try again.", comment: "")
  272. alert.runModal()
  273. }
  274. }
  275. }
  276. //MARK: - KMLinkEmailViewDelegate
  277. extension KMLinkViewController: KMLinkEmailViewDelegate {
  278. func kmLinkEmailViewDidGo(_ view: KMLinkEmailView, _ emailString: String) {
  279. guard let activeAnnotation = current_Annotation else {
  280. return
  281. }
  282. if !KMNTools.isValidateEmail(emailString) {
  283. let alert = NSAlert()
  284. alert.alertStyle = .critical
  285. alert.messageText = KMLocalizedString("Invalid Email. Please try again.", comment: "")
  286. alert.runModal()
  287. return
  288. }
  289. if let url = activeAnnotation.url() {
  290. NSWorkspace.shared.open(URL(string: url)!)
  291. }
  292. }
  293. }
  294. //MARK: - KMNAlignmentControllerDelegate
  295. extension KMLinkViewController: KMNAlignmentControllerDelegate {
  296. func alignmentControllerDidClick(_ controller: KMNAlignmentController, _ alignmentType: KMPDFActiveFormsAlignType) {
  297. pdfView?.change(annotations, alignmentType: alignmentType)
  298. pdfView?.setNeedsDisplayForVisiblePages()
  299. }
  300. }
  301. //MARK: - KMLinkViewController Class Method
  302. extension KMLinkViewController {
  303. }