CPageEditToolBar.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. //
  2. // CPageEditToolBar.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. public enum CPageEditToolBarType: Int {
  15. case insert = 0
  16. case replace
  17. case extract
  18. case copy
  19. case rotate
  20. case delete
  21. }
  22. public protocol CPageEditToolBarDelegate: AnyObject {
  23. func pageEditToolBarBlankPageInsert(_ pageEditToolBar: CPageEditToolBar, pageModel: CBlankPageModel)
  24. func pageEditToolBarPDFInsert(_ pageEditToolBar: CPageEditToolBar, pageModel: CBlankPageModel, document: CPDFDocument)
  25. func pageEditToolBarExtract(_ pageEditToolBar: CPageEditToolBar)
  26. func pageEditToolBarRotate(_ pageEditToolBar: CPageEditToolBar)
  27. func pageEditToolBarDelete(_ pageEditToolBar: CPageEditToolBar)
  28. func pageEditToolBarCopy(_ pageEditToolBar: CPageEditToolBar)
  29. func pageEditToolBarReplace(_ pageEditToolBar: CPageEditToolBar, document: CPDFDocument)
  30. }
  31. public class CPageEditToolBar: UIView, UIDocumentPickerDelegate, CPDFPageInsertViewControllerDelegate, CPDFPDFInsertViewControllerDelegate, CDocumentPasswordViewControllerDelegate {
  32. public weak var delegate: CPageEditToolBarDelegate?
  33. public weak var parentVC: UIViewController?
  34. public var pdfView: CPDFView?
  35. public var currentPageIndex: Int = 0
  36. public var isSelect: Bool = false
  37. public var pageEditBtns: [UIButton]?
  38. private var scrollView: UIScrollView?
  39. private var selectedIndex: Int = 0
  40. private var insertDocument: CPDFDocument?
  41. private var replaceDocument: CPDFDocument?
  42. private var loadingView: CActivityIndicatorView?
  43. // MARK: - Initializers
  44. override init(frame: CGRect) {
  45. super.init(frame: frame)
  46. self.backgroundColor = CPDFColorUtils.CPDFViewControllerBackgroundColor()
  47. let line = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.size.width, height: 1))
  48. line.backgroundColor = UIColor(red: 210.0/255.0, green: 210.0/255.0, blue: 210.0/255.0, alpha: 1.0)
  49. line.autoresizingMask = .flexibleWidth
  50. self.addSubview(line)
  51. self.selectedIndex = -1
  52. self.initSubview()
  53. }
  54. required init?(coder: NSCoder) {
  55. fatalError("init(coder:) has not been implemented")
  56. }
  57. public override func layoutSubviews() {
  58. super.layoutSubviews()
  59. self.scrollView?.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
  60. }
  61. // MARK: - Public Methods
  62. func reloadData() {
  63. // Implementation
  64. if selectedIndex >= 0 && (selectedIndex < pageEditBtns?.count ?? 0) {
  65. var selectedButton = pageEditBtns?[selectedIndex]
  66. selectedButton?.backgroundColor = UIColor.clear
  67. }
  68. selectedIndex = -1
  69. }
  70. // MARK: - Private Methods
  71. func initSubview() {
  72. scrollView = UIScrollView(frame: self.bounds)
  73. scrollView?.showsVerticalScrollIndicator = false
  74. scrollView?.showsHorizontalScrollIndicator = false
  75. self.addSubview(scrollView!)
  76. var offsetX: CGFloat = 20.0
  77. let buttonOffset: CGFloat = 25
  78. let buttonSize: CGFloat = 50
  79. let topOffset = (60 - buttonSize) / 2
  80. let images = ["CPageEditToolBarImageInsert", "CPageEditToolBarImageRepalce", "CPageEditToolBarImageExtract", "CPageEditToolBarImageCopy", "CPageEditToolBarImageRotate", "CPageEditToolBarImageRemove"]
  81. let names = [NSLocalizedString("Insert", comment: ""), NSLocalizedString("Replace", comment: ""), NSLocalizedString("Extract", comment: ""), NSLocalizedString("Copy", comment: ""), NSLocalizedString("Rotate", comment: ""), NSLocalizedString("Delete", comment: "")]
  82. var pageEditBtns = [UIButton]()
  83. for i in 0..<images.count {
  84. let button = UIButton(type: .custom)
  85. button.frame = CGRect(x: offsetX, y: topOffset, width: buttonSize, height: buttonSize)
  86. button.setImage(UIImage(named: images[i], in: Bundle(for: self.classForCoder), compatibleWith: nil), for: .normal)
  87. button.setTitle(names[i], for: .normal)
  88. button.setTitleColor(CPDFColorUtils.CPageEditToolbarFontColor(), for: .normal)
  89. button.layer.cornerRadius = 5.0
  90. button.titleLabel?.font = UIFont.systemFont(ofSize: 12.0)
  91. button.tag = i
  92. button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 18, bottom: 24, right: 10)
  93. button.titleEdgeInsets = UIEdgeInsets(top: button.imageView?.frame.size.height ?? 0, left: -(button.imageView?.frame.size.width ?? 0) , bottom: -1, right: -11)
  94. button.addTarget(self, action: #selector(buttonItemClicked_switch(_:)), for: .touchUpInside)
  95. scrollView?.addSubview(button)
  96. pageEditBtns.append(button)
  97. if i != images.count - 1 {
  98. offsetX += button.bounds.size.width + buttonOffset
  99. } else {
  100. offsetX += button.bounds.size.width + 10
  101. }
  102. }
  103. self.pageEditBtns = pageEditBtns
  104. scrollView?.contentSize = CGSize(width: offsetX, height: scrollView?.bounds.size.height ?? 0)
  105. }
  106. func insertPage() {
  107. let tRootViewControl = parentVC
  108. let insertBlankPageAction = UIAlertAction(title: NSLocalizedString("Blank Page", comment: ""), style: .default) { [weak self] action in
  109. guard let self = self else { return }
  110. let pageInsertVC = CPDFPageInsertViewController()
  111. pageInsertVC.currentPageIndex = self.currentPageIndex
  112. pageInsertVC.currentPageCout = Int(self.pdfView?.document?.pageCount ?? 0)
  113. pageInsertVC.delegate = self
  114. if(tRootViewControl != nil) {
  115. let presentationController = AAPLCustomPresentationController(presentedViewController: pageInsertVC, presenting: tRootViewControl!)
  116. pageInsertVC.transitioningDelegate = presentationController
  117. tRootViewControl?.present(pageInsertVC, animated: true, completion: nil)
  118. }
  119. }
  120. let insertPdfPageAction = UIAlertAction(title: NSLocalizedString("From PDF", comment: ""), style: .default) { [weak self] action in
  121. self?.enterPDFAddFile()
  122. }
  123. let cancelAction = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { [weak self] action in
  124. self?.reloadData()
  125. }
  126. let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
  127. alertController.addAction(insertBlankPageAction)
  128. alertController.addAction(insertPdfPageAction)
  129. alertController.addAction(cancelAction)
  130. if UIDevice.current.userInterfaceIdiom == .pad {
  131. alertController.popoverPresentationController?.sourceView = self.pageEditBtns?.first
  132. alertController.popoverPresentationController?.sourceRect = self.pageEditBtns?.first?.bounds ?? CGRect.zero
  133. }
  134. tRootViewControl?.present(alertController, animated: true)
  135. }
  136. func enterPDFAddFile() {
  137. DispatchQueue.global(qos: .default).async {
  138. DispatchQueue.main.async {
  139. let documentTypes = ["com.adobe.pdf"]
  140. let documentPickerViewController = UIDocumentPickerViewController(documentTypes: documentTypes, in: .open)
  141. documentPickerViewController.delegate = self
  142. guard let tRootViewControl = self.parentVC else { return }
  143. tRootViewControl.present(documentPickerViewController, animated: true, completion: nil)
  144. }
  145. }
  146. }
  147. func handleDocument() {
  148. if CPageEditToolBarType(rawValue: selectedIndex) == CPageEditToolBarType.insert {
  149. if(insertDocument != nil) {
  150. let pageInsertVC = CPDFPDFInsertViewController(document: insertDocument!)
  151. pageInsertVC.currentPageIndex = self.currentPageIndex
  152. pageInsertVC.currentPageCout = Int(self.pdfView?.document?.pageCount ?? 0)
  153. pageInsertVC.delegate = self
  154. guard let tRootViewControl = self.parentVC else { return }
  155. let presentationController = AAPLCustomPresentationController(presentedViewController: pageInsertVC, presenting: tRootViewControl)
  156. pageInsertVC.transitioningDelegate = presentationController
  157. tRootViewControl.present(pageInsertVC, animated: true, completion: nil)
  158. }
  159. } else if CPageEditToolBarType(rawValue: selectedIndex) == CPageEditToolBarType.replace {
  160. if(replaceDocument != nil) {
  161. delegate?.pageEditToolBarReplace(self, document: replaceDocument!)
  162. }
  163. }
  164. }
  165. func popoverWarning() {
  166. let OKAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default) {
  167. action in
  168. // Handle OK action
  169. }
  170. let alert = UIAlertController(title: NSLocalizedString("Warning", comment: ""), message: NSLocalizedString("The page range is invalid or out of range. Please enter the valid page.", comment: ""), preferredStyle: .alert)
  171. alert.addAction(OKAction)
  172. guard let tRootViewControl = self.parentVC else { return }
  173. tRootViewControl.present(alert, animated: true, completion: nil)
  174. }
  175. // MARK: - Action
  176. @objc func buttonItemClicked_switch(_ button: UIButton) {
  177. if selectedIndex >= 0 && selectedIndex < (pageEditBtns?.count ?? 0) {
  178. let selectedButton = pageEditBtns![selectedIndex]
  179. selectedButton.backgroundColor = UIColor.clear
  180. }
  181. selectedIndex = button.tag
  182. switch button.tag {
  183. case CPageEditToolBarType.insert.rawValue:
  184. insertPage()
  185. break
  186. case CPageEditToolBarType.replace.rawValue:
  187. if isSelect {
  188. enterPDFAddFile()
  189. } else {
  190. popoverWarning()
  191. }
  192. break
  193. case CPageEditToolBarType.extract.rawValue:
  194. if isSelect {
  195. delegate?.pageEditToolBarExtract(self)
  196. } else {
  197. popoverWarning()
  198. }
  199. break
  200. case CPageEditToolBarType.rotate.rawValue:
  201. if isSelect {
  202. delegate?.pageEditToolBarRotate(self)
  203. } else {
  204. popoverWarning()
  205. }
  206. break
  207. case CPageEditToolBarType.copy.rawValue:
  208. if isSelect {
  209. delegate?.pageEditToolBarCopy(self)
  210. } else {
  211. popoverWarning()
  212. }
  213. break
  214. case CPageEditToolBarType.delete.rawValue:
  215. if isSelect {
  216. delegate?.pageEditToolBarDelete(self)
  217. } else {
  218. popoverWarning()
  219. }
  220. break
  221. default:
  222. break
  223. }
  224. }
  225. // MARK: - CPDFPageInsertViewControllerDelegate
  226. func pageInsertViewControllerSave(_ pageInsertViewController: CPDFPageInsertViewController, pageModel: CBlankPageModel) {
  227. delegate?.pageEditToolBarBlankPageInsert(self, pageModel: pageModel)
  228. reloadData()
  229. }
  230. func pageInsertViewControllerCancel(_ pageInsertViewController: CPDFPageInsertViewController) {
  231. reloadData()
  232. }
  233. // MARK: - CPDFPDFInsertViewControllerDelegate
  234. func pdfInsertViewControllerCancel(_ pageInsertViewController: CPDFPDFInsertViewController) {
  235. reloadData()
  236. }
  237. func pdfInsertViewControllerSave(_ pageInsertViewController: CPDFPDFInsertViewController, document: CPDFDocument, pageModel: CBlankPageModel) {
  238. insertDocument = document
  239. if(insertDocument != nil) {
  240. delegate?.pageEditToolBarPDFInsert(self, pageModel: pageModel, document: insertDocument!)
  241. }
  242. }
  243. // MARK: - UIDocumentPickerDelegate
  244. public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
  245. let fileUrlAuthozied = urls.first?.startAccessingSecurityScopedResource() ?? false
  246. if fileUrlAuthozied {
  247. let fileCoordinator = NSFileCoordinator()
  248. var error: NSError?
  249. fileCoordinator.coordinate(readingItemAt: urls.first!, options: [], error: &error) { newURL in
  250. let documentFolder = NSHomeDirectory() + "/Documents/Files"
  251. if !FileManager.default.fileExists(atPath: documentFolder) {
  252. try? FileManager.default.createDirectory(atPath: documentFolder, withIntermediateDirectories: true, attributes: nil)
  253. }
  254. let documentPath = documentFolder+"/"+newURL.lastPathComponent
  255. if !FileManager.default.fileExists(atPath: documentPath) {
  256. try? FileManager.default.copyItem(atPath: newURL.path, toPath: documentPath)
  257. }
  258. let url = URL(fileURLWithPath: documentPath)
  259. guard let document = CPDFDocument(url: url) else {
  260. print("Document is NULL")
  261. return
  262. }
  263. if let error = document.error, error._code != CPDFDocumentPasswordError {
  264. let okAction = UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default) { _ in }
  265. let alert = UIAlertController(title: "", message: NSLocalizedString("Sorry PDF Reader Can't open this pdf file!", comment: ""), preferredStyle: .alert)
  266. alert.addAction(okAction)
  267. guard let tRootViewControl = self.parentVC else { return }
  268. tRootViewControl.present(alert, animated: true, completion: nil)
  269. } else {
  270. if document.isLocked {
  271. let documentPasswordVC = CDocumentPasswordViewController(document: document)
  272. documentPasswordVC.delegate = self
  273. documentPasswordVC.modalPresentationStyle = .fullScreen
  274. guard let tRootViewControl = self.parentVC else { return }
  275. tRootViewControl.present(documentPasswordVC, animated: true, completion: nil)
  276. } else {
  277. if CPageEditToolBarType(rawValue: selectedIndex) == .insert {
  278. insertDocument = document
  279. } else if CPageEditToolBarType(rawValue: selectedIndex) == .replace {
  280. replaceDocument = document
  281. }
  282. handleDocument()
  283. }
  284. }
  285. }
  286. urls.first?.stopAccessingSecurityScopedResource()
  287. }
  288. }
  289. public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
  290. reloadData()
  291. }
  292. // MARK: - CDocumentPasswordViewControllerDelegate
  293. public func documentPasswordViewControllerCancel(_ documentPasswordViewController: CDocumentPasswordViewController) {
  294. reloadData()
  295. }
  296. public func documentPasswordViewControllerOpen(_ documentPasswordViewController: CDocumentPasswordViewController, document: CPDFDocument) {
  297. if CPageEditToolBarType(rawValue: selectedIndex) == .insert {
  298. insertDocument = document
  299. } else if CPageEditToolBarType(rawValue: selectedIndex) == .replace {
  300. replaceDocument = document
  301. }
  302. handleDocument()
  303. reloadData()
  304. }
  305. }