CPDFLinkViewController.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. //
  2. // CPDFLinkViewController.swift
  3. // ComPDFKit_Tools
  4. //
  5. // Copyright © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
  6. //
  7. // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
  8. // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
  9. // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
  10. // This notice may not be removed from this file.
  11. //
  12. import UIKit
  13. import ComPDFKit
  14. enum CPDFLinkType: Int {
  15. case link = 0
  16. case page
  17. case email
  18. }
  19. @objc protocol CPDFLinkViewControllerDelegate: AnyObject {
  20. @objc optional func linkViewController(_ linkViewController: CPDFLinkViewController, linkType: Int, linkString: String)
  21. @objc optional func linkViewControllerDismiss(_ linkViewController: CPDFLinkViewController, isLink: Bool)
  22. }
  23. class CPDFLinkViewController: UIViewController,UITextFieldDelegate {
  24. weak var delegate: CPDFLinkViewControllerDelegate?
  25. var pageCount: Int = 1
  26. var annotStyle: CAnnotStyle?
  27. var scrollView: UIScrollView?
  28. var backBtn: UIButton?
  29. var titleLabel: UILabel?
  30. var segmentedControl: UISegmentedControl?
  31. var pageTextField: UITextField?
  32. var emailTextField: UITextField?
  33. var urlTextField: UITextField?
  34. var saveButton: UIButton?
  35. var headerView: UIView?
  36. init(annotStyle: CAnnotStyle) {
  37. super.init(nibName: nil, bundle: nil)
  38. self.annotStyle = annotStyle
  39. }
  40. required init?(coder: NSCoder) {
  41. fatalError("init(coder:) has not been implemented")
  42. }
  43. override func viewDidLoad() {
  44. super.viewDidLoad()
  45. self.view.backgroundColor = CPDFColorUtils.CAnnotationSampleBackgoundColor()
  46. self.headerView = UIView()
  47. self.headerView?.layer.borderColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.1).cgColor
  48. self.headerView?.layer.borderWidth = 1.0
  49. self.headerView?.backgroundColor = CPDFColorUtils.CAnnotationPropertyViewControllerBackgoundColor()
  50. if headerView != nil {
  51. self.view.addSubview(self.headerView!)
  52. }
  53. initWithView()
  54. let buttonWidgetAnnotation = self.annotStyle?.annotations.first
  55. if !(self.annotStyle?.isSelectAnnot ?? false) {
  56. self.linkType = CPDFLinkType.link
  57. self.segmentedControl?.selectedSegmentIndex = 0
  58. } else if buttonWidgetAnnotation != nil && buttonWidgetAnnotation is CPDFButtonWidgetAnnotation {
  59. self.segmentedControl?.selectedSegmentIndex = 0
  60. self.linkType = CPDFLinkType.link
  61. } else {
  62. if buttonWidgetAnnotation != nil && buttonWidgetAnnotation is CPDFLinkAnnotation {
  63. let link = buttonWidgetAnnotation as! CPDFLinkAnnotation
  64. let url = link.url()
  65. let destination = link.destination()
  66. if url != nil {
  67. if url?.hasPrefix("mailto:") == true {
  68. emailTextField?.text = String(url!.dropFirst(7))
  69. self.linkType = CPDFLinkType.email
  70. self.segmentedControl?.selectedSegmentIndex = 2
  71. } else {
  72. self.urlTextField?.text = url
  73. self.linkType = CPDFLinkType.link
  74. self.segmentedControl?.selectedSegmentIndex = 0
  75. }
  76. } else if destination != nil {
  77. self.linkType = CPDFLinkType.page
  78. self.pageTextField?.text = "\(destination!.pageIndex + 1)"
  79. self.segmentedControl?.selectedSegmentIndex = 1
  80. } else {
  81. self.linkType = CPDFLinkType.link
  82. self.segmentedControl?.selectedSegmentIndex = 0
  83. }
  84. }
  85. }
  86. updatePreferredContentSize(with: self.traitCollection)
  87. }
  88. override func viewWillAppear(_ animated: Bool) {
  89. super.viewWillAppear(animated)
  90. var currentTextField: UITextField?
  91. switch linkType {
  92. case .link:
  93. currentTextField = urlTextField
  94. case .page:
  95. currentTextField = pageTextField
  96. default:
  97. currentTextField = emailTextField
  98. }
  99. currentTextField?.becomeFirstResponder()
  100. }
  101. var isLink: Bool {
  102. var currentTextField: String?
  103. switch segmentedControl?.selectedSegmentIndex {
  104. case 0:
  105. currentTextField = urlTextField?.text
  106. case 1:
  107. currentTextField = pageTextField?.text
  108. default:
  109. currentTextField = emailTextField?.text
  110. }
  111. if let text = currentTextField, !text.isEmpty {
  112. return true
  113. } else {
  114. return false
  115. }
  116. }
  117. var linkType: CPDFLinkType = .link {
  118. didSet {
  119. let currentTextField: UITextField?
  120. switch linkType {
  121. case .link:
  122. pageTextField?.isHidden = true
  123. emailTextField?.isHidden = true
  124. urlTextField?.isHidden = false
  125. currentTextField = urlTextField
  126. case .page:
  127. urlTextField?.isHidden = true
  128. emailTextField?.isHidden = true
  129. pageTextField?.isHidden = false
  130. currentTextField = pageTextField
  131. case .email:
  132. urlTextField?.isHidden = true
  133. pageTextField?.isHidden = true
  134. emailTextField?.isHidden = false
  135. currentTextField = emailTextField
  136. }
  137. currentTextField?.becomeFirstResponder()
  138. if let text = currentTextField?.text, !text.isEmpty {
  139. saveButton?.isEnabled = true
  140. saveButton?.backgroundColor = UIColor.systemBlue
  141. saveButton?.setTitleColor(UIColor.white, for: .normal)
  142. } else {
  143. saveButton?.isEnabled = false
  144. saveButton?.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2)
  145. saveButton?.setTitleColor(UIColor.lightGray, for: .normal)
  146. }
  147. }
  148. }
  149. override func viewWillLayoutSubviews() {
  150. super.viewWillLayoutSubviews()
  151. titleLabel?.frame = CGRect(x: (view.frame.size.width - 120)/2, y: 5, width: 120, height: 50)
  152. headerView?.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50)
  153. if #available(iOS 11.0, *) {
  154. backBtn?.frame = CGRect(x: view.frame.size.width - 60 - view.safeAreaInsets.right, y: 5, width: 50, height: 50)
  155. } else {
  156. backBtn?.frame = CGRect(x: view.frame.size.width - 60, y: 5, width: 50, height: 50)
  157. }
  158. if #available(iOS 11.0, *) {
  159. scrollView?.frame = CGRect(x: view.safeAreaInsets.left, y: 50, width: view.frame.size.width - view.safeAreaInsets.left - view.safeAreaInsets.right, height: view.frame.size.height)
  160. } else {
  161. scrollView?.frame = CGRect(x: 0, y: 50, width: view.frame.size.width, height: view.frame.size.height)
  162. }
  163. scrollView?.contentSize = CGSize(width: scrollView?.frame.size.width ?? 0, height: scrollView?.contentSize.height ?? 0)
  164. saveButton?.frame = CGRect(x: ((scrollView?.frame.size.width ?? 0) - 120)/2, y: saveButton?.frame.origin.y ?? 0, width: 120, height: 32)
  165. }
  166. override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
  167. super.willTransition(to: newCollection, with: coordinator)
  168. updatePreferredContentSize(with: newCollection)
  169. }
  170. func updatePreferredContentSize(with traitCollection: UITraitCollection) {
  171. preferredContentSize = CGSize(width: view.bounds.size.width, height: traitCollection.verticalSizeClass == .compact ? 350 : 600)
  172. urlTextField?.resignFirstResponder()
  173. emailTextField?.resignFirstResponder()
  174. pageTextField?.resignFirstResponder()
  175. }
  176. func initWithView() {
  177. titleLabel = UILabel()
  178. titleLabel?.autoresizingMask = .flexibleRightMargin
  179. titleLabel?.text = NSLocalizedString("Link to", comment: "")
  180. titleLabel?.textAlignment = .center
  181. titleLabel?.font = UIFont.systemFont(ofSize: 20)
  182. titleLabel?.adjustsFontSizeToFitWidth = true
  183. if titleLabel != nil {
  184. headerView?.addSubview(titleLabel!)
  185. }
  186. scrollView = UIScrollView()
  187. scrollView?.frame = CGRect(x: 0, y: 50, width: view.frame.size.width, height: view.frame.size.height)
  188. scrollView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  189. scrollView?.isScrollEnabled = true
  190. if scrollView != nil {
  191. view.addSubview(scrollView!)
  192. }
  193. backBtn = UIButton(type: .custom)
  194. if #available(iOS 11.0, *) {
  195. backBtn?.frame = CGRect(x: view.frame.size.width - 60 - view.safeAreaInsets.right, y: 5, width: 50, height: 50)
  196. } else {
  197. backBtn?.frame = CGRect(x: view.frame.size.width - 60, y: 5, width: 50, height: 50)
  198. }
  199. backBtn?.autoresizingMask = .flexibleLeftMargin
  200. backBtn?.setImage(UIImage(named: "CPDFAnnotationBaseImageBack", in: Bundle(for: type(of: self)), compatibleWith: nil), for: .normal)
  201. backBtn?.addTarget(self, action: #selector(buttonItemClicked_back(_:)), for: .touchUpInside)
  202. if backBtn != nil {
  203. headerView?.addSubview(backBtn!)
  204. }
  205. var offstY: CGFloat = 10
  206. segmentedControl = UISegmentedControl(items: [NSLocalizedString("URL", comment: ""), NSLocalizedString("Page", comment: ""), NSLocalizedString("Email", comment: "")])
  207. segmentedControl?.frame = CGRect(x: 30, y: offstY, width: scrollView!.frame.size.width - 30 * 2, height: 32.0)
  208. segmentedControl?.autoresizingMask = .flexibleWidth
  209. segmentedControl?.addTarget(self, action: #selector(segmentedControlValueChanged_Mode(_:)), for: .valueChanged)
  210. if segmentedControl != nil {
  211. scrollView?.addSubview(segmentedControl!)
  212. }
  213. offstY += segmentedControl?.frame.size.height ?? 0
  214. offstY += 32.0
  215. urlTextField = UITextField(frame: CGRect(x: 30.0, y: offstY, width: scrollView!.frame.size.width - 60.0, height: 28.0))
  216. urlTextField?.autoresizingMask = .flexibleWidth
  217. urlTextField?.layer.borderWidth = 1.0
  218. urlTextField?.layer.borderColor = UIColor.lightGray.cgColor
  219. urlTextField?.layer.cornerRadius = 5.0
  220. urlTextField?.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  221. urlTextField?.leftViewMode = .always
  222. urlTextField?.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  223. urlTextField?.rightViewMode = .always
  224. urlTextField?.delegate = self
  225. urlTextField?.isHidden = true
  226. urlTextField?.font = UIFont.systemFont(ofSize: 18.0)
  227. urlTextField?.placeholder = "https://www.compdf.com"
  228. if urlTextField != nil {
  229. scrollView?.addSubview(urlTextField!)
  230. }
  231. pageTextField = UITextField(frame: CGRect(x: 30.0, y: offstY, width: view.frame.size.width - 60.0, height: 28.0))
  232. pageTextField?.autoresizingMask = .flexibleWidth
  233. pageTextField?.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  234. pageTextField?.layer.borderColor = UIColor.lightGray.cgColor
  235. pageTextField?.leftViewMode = .always
  236. pageTextField?.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  237. pageTextField?.rightViewMode = .always
  238. pageTextField?.isHidden = true
  239. pageTextField?.layer.borderWidth = 1.0
  240. pageTextField?.layer.cornerRadius = 5.0
  241. pageTextField?.delegate = self
  242. pageTextField?.font = UIFont.systemFont(ofSize: 18.0)
  243. let str = String(format: "1~%ld", self.pageCount)
  244. pageTextField?.placeholder = NSLocalizedString(str, comment: "")
  245. pageTextField?.keyboardType = .numberPad
  246. if pageTextField != nil {
  247. scrollView?.addSubview(pageTextField!)
  248. }
  249. emailTextField = UITextField(frame: CGRect(x: 30.0, y: offstY, width: view.frame.size.width - 60.0, height: 28.0))
  250. emailTextField?.autoresizingMask = .flexibleWidth
  251. emailTextField?.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  252. emailTextField?.layer.borderColor = UIColor.lightGray.cgColor
  253. emailTextField?.leftViewMode = .always
  254. emailTextField?.rightView = UIView(frame: CGRect(x: 0, y: 0, width: 8, height: 0))
  255. emailTextField?.rightViewMode = .always
  256. emailTextField?.isHidden = true
  257. emailTextField?.layer.borderWidth = 1.0
  258. emailTextField?.layer.cornerRadius = 5.0
  259. emailTextField?.delegate = self
  260. emailTextField?.font = UIFont.systemFont(ofSize: 18.0)
  261. emailTextField?.placeholder = NSLocalizedString("support@compdf.com", comment: "")
  262. if emailTextField != nil {
  263. scrollView?.addSubview(emailTextField!)
  264. }
  265. offstY += urlTextField?.frame.size.height ?? 0
  266. emailTextField?.addTarget(self, action: #selector(textFieldTextChange(_:)), for: .editingChanged)
  267. pageTextField?.addTarget(self, action: #selector(textFieldTextChange(_:)), for: .editingChanged)
  268. urlTextField?.addTarget(self, action: #selector(textFieldTextChange(_:)), for: .editingChanged)
  269. offstY += 30.0
  270. saveButton = UIButton(type: .custom)
  271. saveButton?.frame = CGRect(x: ((scrollView?.frame.size.width ?? 0) - 120)/2, y: offstY, width: 120, height: 32)
  272. saveButton?.layer.cornerRadius = 5.0
  273. saveButton?.autoresizingMask = .flexibleLeftMargin
  274. saveButton?.setTitle(NSLocalizedString("Save", comment: ""), for: .normal)
  275. saveButton?.setTitleColor(.white, for: .normal)
  276. saveButton?.addTarget(self, action: #selector(buttonItemClicked_Save(_:)), for: .touchUpInside)
  277. saveButton?.backgroundColor = .systemBlue
  278. if saveButton != nil {
  279. scrollView?.addSubview(saveButton!)
  280. }
  281. offstY += saveButton?.frame.size.height ?? 0
  282. scrollView?.contentSize = CGSize(width: view.frame.size.width, height: view.frame.size.height)
  283. NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHidez(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
  284. NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
  285. }
  286. // MARK: - Action
  287. @objc func buttonItemClicked_back(_ button: UIButton) {
  288. var currentTextField: String?
  289. switch segmentedControl?.selectedSegmentIndex {
  290. case 0:
  291. currentTextField = urlTextField?.text
  292. case 1:
  293. currentTextField = pageTextField?.text
  294. default:
  295. currentTextField = emailTextField?.text
  296. }
  297. let isLink: Bool
  298. if let currentTextField = currentTextField, !currentTextField.isEmpty {
  299. isLink = true
  300. } else {
  301. isLink = false
  302. }
  303. dismiss(animated: true) {
  304. self.delegate?.linkViewControllerDismiss?(self, isLink: isLink)
  305. }
  306. }
  307. @objc func segmentedControlValueChanged_Mode(_ button: UISegmentedControl) {
  308. var currentTextField: String?
  309. switch segmentedControl?.selectedSegmentIndex {
  310. case 0:
  311. self.linkType = .link
  312. currentTextField = urlTextField?.text
  313. case 1:
  314. self.linkType = .page
  315. currentTextField = pageTextField?.text
  316. default:
  317. self.linkType = .email
  318. currentTextField = emailTextField?.text
  319. }
  320. }
  321. @objc func buttonItemClicked_Save(_ button: UIButton) {
  322. var string: String?
  323. if .link == self.linkType {
  324. string = urlTextField?.text?.lowercased()
  325. if !(string?.hasPrefix("https://") ?? false) && !(string?.hasPrefix("http://") ?? false) {
  326. string = "https://\(string!)"
  327. }
  328. } else if CPDFLinkType.page == linkType {
  329. string = pageTextField?.text
  330. let annotation = annotStyle?.annotations.first
  331. let document = annotation?.page?.document
  332. let pageNumber = Int(string ?? "")
  333. if (pageNumber != nil) {
  334. if pageNumber! > document?.pageCount ?? 0 || pageNumber! < 1 {
  335. let alert = UIAlertController(title: "", message: NSLocalizedString("Config Error", comment: ""), preferredStyle: .alert)
  336. let okAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default) { action in
  337. self.pageTextField?.text = ""
  338. }
  339. alert.addAction(okAction)
  340. present(alert, animated: true, completion: nil)
  341. return
  342. }
  343. } else {
  344. let alert = UIAlertController(title: "", message: NSLocalizedString("Config Error", comment: ""), preferredStyle: .alert)
  345. let okAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default) { action in
  346. self.pageTextField?.text = ""
  347. }
  348. alert.addAction(okAction)
  349. present(alert, animated: true, completion: nil)
  350. return
  351. }
  352. } else if CPDFLinkType.email == linkType {
  353. string = emailTextField?.text
  354. if !(string?.hasPrefix("mailto:") ?? false) {
  355. string = "mailto:\(string!)"
  356. }
  357. }
  358. if let mAnnotation = annotStyle?.annotations.first as? CPDFButtonWidgetAnnotation {
  359. if linkType == CPDFLinkType.email || linkType == CPDFLinkType.link {
  360. let urlAction = CPDFURLAction(url: string)
  361. mAnnotation.setAction(urlAction)
  362. } else {
  363. }
  364. }
  365. dismiss(animated: true) {
  366. self.delegate?.linkViewController?(self, linkType: self.linkType.rawValue, linkString: string ?? "")
  367. }
  368. }
  369. @objc func textFieldTextChange(_ textField: UITextField) {
  370. if let text = textField.text, !text.isEmpty {
  371. saveButton?.isEnabled = true
  372. saveButton?.backgroundColor = UIColor(red: 20.0/255.0, green: 96.0/255.0, blue: 243.0/255.0, alpha: 1.0)
  373. saveButton?.setTitleColor(.white, for: .normal)
  374. } else {
  375. saveButton?.isEnabled = false
  376. saveButton?.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2)
  377. saveButton?.setTitleColor(.lightGray, for: .normal)
  378. }
  379. if textField == pageTextField {
  380. if let pageText = pageTextField?.text, let pageNumber = Int(pageText), pageNumber > pageCount {
  381. saveButton?.isEnabled = false
  382. saveButton?.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2)
  383. saveButton?.setTitleColor(.lightGray, for: .normal)
  384. }
  385. }
  386. }
  387. // MARK: - UITextFieldDelegate
  388. func textFieldShouldReturn(_ textField: UITextField) -> Bool {
  389. textField.resignFirstResponder()
  390. return true
  391. }
  392. @objc func keyboardWillHidez(_ notification: Notification) {
  393. guard let userInfo = notification.userInfo,
  394. let keyboardFrameValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {
  395. return
  396. }
  397. let keyboardFrame = keyboardFrameValue.cgRectValue
  398. let textFieldFrame = urlTextField?.convert(urlTextField?.frame ?? CGRect.zero, to: view)
  399. if textFieldFrame?.maxY ?? 0 > view.frame.size.height - keyboardFrame.size.height {
  400. var insets = scrollView?.contentInset
  401. insets?.bottom = keyboardFrame.size.height + (urlTextField?.frame.size.height ?? 0)
  402. scrollView?.contentInset = insets ?? UIEdgeInsets.zero
  403. }
  404. }
  405. @objc func keyboardWillHide(_ notification: Notification) {
  406. var insets = scrollView?.contentInset
  407. insets?.bottom = 0
  408. scrollView?.contentInset = insets ?? UIEdgeInsets.zero
  409. }
  410. }