CPDFBookmarkViewController.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //
  2. // CPDFBookmarkViewController.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. @objc protocol CPDFBookmarkViewControllerDelegate: AnyObject {
  15. @objc optional func boomarkViewController(_ boomarkViewController: CPDFBookmarkViewController,pageIndex:NSInteger)
  16. }
  17. class CPDFBookmarkViewController: UIViewController {
  18. weak var delegate: CPDFBookmarkViewControllerDelegate?
  19. weak var pdfView:CPDFView?
  20. var bookmarks:[CPDFBookmark]?
  21. var tableView: UITableView?
  22. var noDataLabel: UILabel?
  23. var addBookmarkBtn: UIButton?
  24. // MARK: - Initializers
  25. init(pdfView: CPDFView) {
  26. super.init(nibName: nil, bundle: nil)
  27. self.pdfView = pdfView
  28. }
  29. required init?(coder: NSCoder) {
  30. fatalError("init(coder:) has not been implemented")
  31. }
  32. // MARK: - UIViewController Methods
  33. override func viewDidLoad() {
  34. super.viewDidLoad()
  35. tableView = UITableView(frame: view.bounds, style: .plain)
  36. tableView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
  37. tableView?.delegate = self
  38. tableView?.dataSource = self
  39. tableView?.rowHeight = UITableView.automaticDimension
  40. tableView?.estimatedRowHeight = 60
  41. tableView?.tableFooterView = UIView()
  42. tableView?.separatorStyle = .none
  43. if(tableView != nil) {
  44. view.addSubview(tableView!)
  45. }
  46. noDataLabel = UILabel()
  47. noDataLabel?.textColor = .gray
  48. noDataLabel?.text = NSLocalizedString("No Bookmarks", comment: "")
  49. noDataLabel?.sizeToFit()
  50. noDataLabel?.center = CGPoint(x: view.bounds.size.width/2.0, y: view.bounds.size.height/2.0)
  51. noDataLabel?.autoresizingMask = [.flexibleTopMargin, .flexibleBottomMargin, .flexibleLeftMargin, .flexibleRightMargin]
  52. if(noDataLabel != nil) {
  53. view.addSubview(noDataLabel!)
  54. }
  55. addBookmarkBtn = UIButton(frame: CGRect(x: view.frame.size.width - 20 - 50, y: view.frame.size.height - 50 - 50, width: 50, height: 50))
  56. if #available(iOS 11.0, *) {
  57. addBookmarkBtn?.frame = CGRect(x: view.frame.size.width - view.safeAreaInsets.right - 50 - 20, y: view.frame.size.height - view.safeAreaInsets.bottom - 50, width: 50, height: 50)
  58. }
  59. addBookmarkBtn?.autoresizingMask = [.flexibleLeftMargin, .flexibleTopMargin]
  60. addBookmarkBtn?.setImage(UIImage(named: "CPDFBookmarkImageAdd", in: Bundle(for: Self.self), compatibleWith: nil), for: .normal)
  61. addBookmarkBtn?.addTarget(self, action: #selector(buttonItemClicked_add(_:)), for: .touchUpInside)
  62. if(addBookmarkBtn != nil) {
  63. self.view.addSubview(addBookmarkBtn!)
  64. }
  65. self.createGestureRecognizer()
  66. }
  67. override func viewDidAppear(_ animated: Bool) {
  68. super.viewDidAppear(animated)
  69. self.reloadData()
  70. }
  71. // MARK: - Private Methods
  72. func reloadData() {
  73. if(pdfView != nil) {
  74. if let bookmarks = pdfView!.document?.bookmarks(), bookmarks.count > 0 {
  75. self.bookmarks = bookmarks
  76. tableView?.isHidden = false
  77. noDataLabel?.isHidden = true
  78. } else {
  79. tableView?.isHidden = true
  80. noDataLabel?.isHidden = false
  81. }
  82. tableView?.reloadData()
  83. }
  84. }
  85. func createGestureRecognizer() {
  86. addBookmarkBtn?.isUserInteractionEnabled = true
  87. let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panaddBookmarkBtn(_:)))
  88. addBookmarkBtn?.addGestureRecognizer(panRecognizer)
  89. }
  90. // MARK: - Action
  91. @objc func panaddBookmarkBtn(_ gestureRecognizer: UIPanGestureRecognizer) {
  92. let point = gestureRecognizer.translation(in: view)
  93. let newX = (addBookmarkBtn?.center.x ?? 0) + point.x
  94. let newY = (addBookmarkBtn?.center.y ?? 0) + point.y
  95. let newPoint = CGPoint(x: newX, y: newY)
  96. if view.frame.contains(newPoint) {
  97. addBookmarkBtn?.center = newPoint
  98. }
  99. gestureRecognizer.setTranslation(.zero, in: view)
  100. }
  101. @objc func buttonItemClicked_add(_ sender: Any) {
  102. if pdfView!.document?.bookmark(forPageIndex: UInt(pdfView!.currentPageIndex)) == nil {
  103. let alert = UIAlertController(title:NSLocalizedString("Add Bookmarks", comment: ""), message: nil, preferredStyle: .alert)
  104. alert.addTextField { textField in
  105. textField.placeholder = NSLocalizedString("Bookmark Title", comment: "")
  106. }
  107. let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
  108. let addAction = UIAlertAction(title: NSLocalizedString("Add", comment: ""), style: .default) { [weak self] action in
  109. if let title = alert.textFields?.first?.text, !title.isEmpty {
  110. self?.pdfView!.document?.addBookmark(title, forPageIndex: UInt(self?.pdfView?.currentPageIndex ?? 0))
  111. if let page = self?.pdfView!.document?.page(at: UInt(self?.pdfView?.currentPageIndex ?? 0)) {
  112. self?.pdfView?.setNeedsDisplayFor(page)
  113. }
  114. self?.reloadData()
  115. }
  116. }
  117. alert.addAction(cancelAction)
  118. alert.addAction(addAction)
  119. present(alert, animated: true, completion: nil)
  120. } else {
  121. let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
  122. let okAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default) { [weak self] action in
  123. guard let self = self, let pdfView = self.pdfView else { return }
  124. pdfView.document?.removeBookmark(forPageIndex: UInt(pdfView.currentPageIndex))
  125. if let page = pdfView.document?.page(at: UInt(pdfView.currentPageIndex)) {
  126. pdfView.setNeedsDisplayFor(page)
  127. }
  128. if(self.tableView != nil) {
  129. self.tableView!.setEditing(false, animated: true)
  130. self.tableView!.isUserInteractionEnabled = true
  131. }
  132. self.reloadData()
  133. }
  134. let alert = UIAlertController(title: "", message: NSLocalizedString("Do you want to remove old mark?", comment: ""), preferredStyle: .alert)
  135. alert.addAction(cancelAction)
  136. alert.addAction(okAction)
  137. present(alert, animated: true, completion: nil)
  138. }
  139. }
  140. }
  141. // MARK: - UITableViewDataSource
  142. extension CPDFBookmarkViewController : UITableViewDataSource {
  143. func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  144. if bookmarks?.count ?? 0 > 0 {
  145. noDataLabel?.isHidden = true
  146. } else {
  147. noDataLabel?.isHidden = false
  148. }
  149. return bookmarks?.count ?? 0
  150. }
  151. func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  152. var cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? CPDFBookmarkViewCell
  153. if(cell == nil) {
  154. cell = CPDFBookmarkViewCell(style: .subtitle, reuseIdentifier: "cell")
  155. }
  156. let bookmark = bookmarks?[indexPath.row]
  157. cell!.pageIndexLabel?.text = "\(NSLocalizedString("Page", comment: "")) \((bookmark?.pageIndex ?? 0) + 1)"
  158. cell!.titleLabel?.text = bookmark?.label ?? ""
  159. return cell!
  160. }
  161. }
  162. // MARK: - UITableViewDelegate
  163. extension CPDFBookmarkViewController : UITableViewDelegate {
  164. func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
  165. let deleteAction = UITableViewRowAction(style: .destructive, title: NSLocalizedString("Delete",comment: "")) { (action, indexPath) in
  166. if let cell = tableView.cellForRow(at: indexPath) as? CPDFBookmarkViewCell {
  167. self.pdfView?.document.removeBookmark(forPageIndex: UInt(cell.pageIndexLabel?.text ?? "0")! - 1)
  168. if var bookmarks = self.bookmarks {
  169. bookmarks.remove(at: indexPath.row)
  170. tableView.deleteRows(at: [indexPath], with: .fade)
  171. tableView.setEditing(false, animated: true)
  172. tableView.isUserInteractionEnabled = true
  173. self.reloadData()
  174. }
  175. }
  176. }
  177. let editAction = UITableViewRowAction(style: .destructive, title: NSLocalizedString("Edit",comment: "")) { (action, indexPath) in
  178. let alert = UIAlertController(title: NSLocalizedString("Edit Bookmark",comment: ""), message: nil, preferredStyle: .alert)
  179. alert.addTextField { (textField) in
  180. textField.placeholder = NSLocalizedString("Bookmark Title", comment: "")
  181. }
  182. let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
  183. let addAction = UIAlertAction(title: NSLocalizedString("Create", comment: ""), style: .default) { (action) in
  184. if let cell = tableView.cellForRow(at: indexPath) as? CPDFBookmarkViewCell {
  185. cell.titleLabel!.text = alert.textFields?.first?.text
  186. self.pdfView!.document.bookmarks()[indexPath.row].label = alert.textFields?.first?.text
  187. }
  188. }
  189. alert.addAction(cancelAction)
  190. alert.addAction(addAction)
  191. self.present(alert, animated: true, completion: nil)
  192. tableView.setEditing(false, animated: true)
  193. tableView.isUserInteractionEnabled = true
  194. }
  195. deleteAction.backgroundColor = UIColor.red
  196. editAction.backgroundColor = UIColor.blue
  197. return [deleteAction, editAction]
  198. }
  199. @available(iOS 11.0, *)
  200. func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
  201. let deleteAction = UIContextualAction(style: .normal, title: nil) { (action, view, completion) in
  202. let bookmark = self.bookmarks?[indexPath.row]
  203. self.pdfView?.document.removeBookmark(forPageIndex: UInt(bookmark?.pageIndex ?? 0))
  204. let page = self.pdfView?.document.page(at: UInt(bookmark?.pageIndex ?? 0))
  205. self.pdfView?.setNeedsDisplayFor(page)
  206. if var bookmarks = self.bookmarks {
  207. bookmarks.remove(at: indexPath.row)
  208. self.bookmarks = bookmarks
  209. tableView.deleteRows(at: [indexPath], with: .fade)
  210. self.tableView?.setEditing(false, animated: true)
  211. self.tableView?.isUserInteractionEnabled = true
  212. self.reloadData()
  213. }
  214. completion(true)
  215. }
  216. let editAction = UIContextualAction(style: .normal, title: nil) { (action, view, completion) in
  217. let alert = UIAlertController(title: NSLocalizedString("Edit Bookmark", comment: ""), message: nil, preferredStyle: .alert)
  218. alert.addTextField { (textField) in
  219. textField.placeholder = NSLocalizedString("Bookmark Title", comment: "")
  220. }
  221. let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
  222. let addAction = UIAlertAction(title: NSLocalizedString("Add", comment: ""), style: .default) { (action) in
  223. if let cell = tableView.cellForRow(at: indexPath) as? CPDFBookmarkViewCell {
  224. cell.titleLabel?.text = alert.textFields?.first?.text
  225. self.pdfView?.document.bookmarks()[indexPath.row].label = alert.textFields?.first?.text
  226. }
  227. }
  228. alert.addAction(cancelAction)
  229. alert.addAction(addAction)
  230. self.present(alert, animated: true, completion: nil)
  231. tableView.setEditing(false, animated: true)
  232. tableView.isUserInteractionEnabled = true
  233. completion(true)
  234. }
  235. deleteAction.image = UIImage(named: "CPDFBookmarkImageDelete", in: Bundle(for: self.classForCoder), compatibleWith: nil)
  236. deleteAction.backgroundColor = UIColor.red
  237. editAction.image = UIImage(named: "CPDFBookmarkImageEraser", in: Bundle(for: self.classForCoder), compatibleWith: nil)
  238. let configuration = UISwipeActionsConfiguration(actions: [deleteAction, editAction])
  239. configuration.performsFirstActionWithFullSwipe = false
  240. return configuration
  241. }
  242. func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
  243. let bookmark = self.bookmarks?[indexPath.row]
  244. self.delegate?.boomarkViewController?(self, pageIndex: bookmark?.pageIndex ?? 0)
  245. }
  246. }