KMHomeViewController+UI.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. //
  2. // KMHomeViewController+UI.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by wanjun on 2022/10/13.
  6. //
  7. import Foundation
  8. extension KMHomeViewController {
  9. func refreshRightBoxUI(_ state: KMHomeToolState) {
  10. rightFullBox.isHidden = true
  11. rightTopBox.isHidden = true
  12. rightBottomBox.isHidden = true
  13. homeButtonVC?.state = .Norm
  14. pdfToolsButtonVC?.state = .Norm
  15. cloudDocumentsButtonVC?.state = .Norm
  16. switch state {
  17. case .Home:
  18. rightTopBox.isHidden = false
  19. rightBottomBox.isHidden = false
  20. rightTopBox.contentView = fastToolViewController.view
  21. rightBottomBox.contentView = historyFileViewController.view
  22. rightFullBox.contentView = nil
  23. let isQuickToolsType:Bool = UserDefaults.standard.bool(forKey: "kHomeQucikToolsTypeKey")
  24. if isQuickToolsType {
  25. rightTopBoxHeightConstraint.constant = 230 + ScrollerViewWidget
  26. } else {
  27. rightTopBoxHeightConstraint.constant = 326 + ScrollerViewWidget
  28. }
  29. homeButtonVC?.state = .Sel
  30. refreshUI()
  31. break
  32. case .PDFTools:
  33. rightFullBox.isHidden = false
  34. rightFullBox.contentView = pdfToolsViewController.view
  35. rightTopBox.contentView = nil
  36. rightBottomBox.contentView = nil
  37. pdfToolsButtonVC?.state = .Sel
  38. refreshUI()
  39. break
  40. case .CloudDocuments:
  41. rightFullBox.isHidden = false
  42. rightFullBox.contentView = cloudDocumentsViewController.view
  43. rightTopBox.contentView = nil
  44. rightBottomBox.contentView = nil
  45. cloudDocumentsButtonVC?.state = .Sel
  46. refreshUI()
  47. break
  48. default:
  49. break
  50. }
  51. }
  52. func showConvertWindow(type: KMPDFConvertType) {
  53. Task { @MainActor in
  54. self.km_secure_openPanel_convert(type: type)
  55. }
  56. }
  57. func km_secure_openPanel_convert(type: KMPDFConvertType) {
  58. DispatchQueue.main.async {
  59. NSOpenPanel.km_secure_openPanel_success(window: self.view.window!) { url, password in
  60. if (url.path.isPDFValid() == false) {
  61. let alert = NSAlert()
  62. alert.alertStyle = .critical
  63. alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "")
  64. alert.runModal()
  65. return
  66. }
  67. self._showConvertWindow(type: type, url: url, password: password)
  68. }
  69. }
  70. }
  71. func showSecurityWindow() {
  72. }
  73. func km_secure_openPanel_security(limit: Bool = false) {
  74. DispatchQueue.main.async {
  75. NSOpenPanel.km_secure_openPanel_success(window: self.view.window!, needOwner: true) { url, password in
  76. self._showSecurityWindow(url: url, password: password, limit: limit)
  77. }
  78. }
  79. }
  80. func refreshScrollView() -> Void {
  81. let rect = self.homeSplitView.frame
  82. let rightWidth = Int(rect.width) - 271
  83. if self.aiOpenPDFFilesViewController != nil {
  84. if rightWidth >= (360 + 20 + 328) {
  85. self.rightTopBoxHeightConstraint.constant = 348
  86. self.aiOpenPDFFilesViewController.refreshLayout(isLimit: false)
  87. } else {
  88. self.rightTopBoxHeightConstraint.constant = 348 * 2
  89. self.aiOpenPDFFilesViewController.refreshLayout(isLimit: true)
  90. }
  91. // let scrollView: NSScrollView = self.homeRightScrollViewView
  92. // let targetOrigin: NSPoint = NSPoint(x: 271, y: (self.homeRightScrollViewView.documentView?.frame.height)!)
  93. //
  94. // let documentVisibleRect = scrollView.documentVisibleRect
  95. // let documentSize = scrollView.documentView?.frame.size ?? .zero
  96. //
  97. // // 确保 targetOrigin 在有效的滚动范围内
  98. // let maxX = max(0, documentSize.width - documentVisibleRect.size.width)
  99. // let maxY = max(0, documentSize.height - documentVisibleRect.size.height)
  100. // let clampedOrigin = NSPoint(x: min(targetOrigin.x, maxX), y: min(targetOrigin.y, maxY))
  101. //
  102. //
  103. //// self.homeRightScrollViewView.documentView?.layoutSubtreeIfNeeded()
  104. // self.homeRightScrollViewView.contentView.scroll(to:clampedOrigin)
  105. }
  106. var contentViewHeight = 0
  107. if self.historyFileViewController.files.count > 0 {
  108. if self.historyFileViewController.showMode == .Thumbnail {
  109. if self.historyFileViewController.thumbnailSCrollView != nil {
  110. var count = rightWidth/(226 + 32)
  111. if count <= 0 {
  112. count = 1
  113. }
  114. var row = self.historyFileViewController.files.count/count
  115. if self.historyFileViewController.files.count%count > 0 {
  116. row += 1
  117. }
  118. let height2 = (248 + 16) * row
  119. contentViewHeight = Int(self.rightTopBoxHeightConstraint.constant + CGFloat(height2) + 76)
  120. self.rightBottonHeight.constant = CGFloat(height2) + 76
  121. }
  122. } else {
  123. if self.historyFileViewController.listScrollView != nil {
  124. let height2 = self.historyFileViewController.files.count * 72 + 32
  125. contentViewHeight = Int(self.rightTopBoxHeightConstraint.constant + CGFloat(height2) + 76)
  126. self.rightBottonHeight.constant = CGFloat(height2) + 76
  127. }
  128. }
  129. } else {
  130. contentViewHeight = Int(rect.height - self.rightTopBox.frame.height)
  131. self.rightBottonHeight.constant = CGFloat(contentViewHeight)
  132. }
  133. if contentViewHeight < Int(rect.height) {
  134. contentViewHeight = Int(rect.height)
  135. self.rightBottonHeight.constant = rect.height - self.rightTopBoxHeightConstraint.constant
  136. }
  137. self.homeRightScrollViewView.documentView!.frame = NSRect(x: 271, y: 0, width: rightWidth, height: contentViewHeight)
  138. let scrollView: NSScrollView = self.homeRightScrollViewView
  139. let targetOrigin: NSPoint = NSPoint(x: 271, y: (self.homeRightScrollViewView.documentView?.frame.height)!)
  140. let documentVisibleRect = scrollView.documentVisibleRect
  141. let documentSize = scrollView.documentView?.frame.size ?? .zero
  142. // 确保 targetOrigin 在有效的滚动范围内
  143. let maxX = max(271, documentSize.width - documentVisibleRect.size.width)
  144. let maxY = max(0, documentSize.height - documentVisibleRect.size.height)
  145. let clampedOrigin = NSPoint(x: min(targetOrigin.x, maxX), y: min(targetOrigin.y, maxY))
  146. self.homeRightScrollViewView.contentView.scroll(to:clampedOrigin)
  147. }
  148. // MARK: - Private Methods
  149. fileprivate func _showConvertWindow(type: KMPDFConvertType, url: URL, password: String? = nil) {
  150. // var windowController: KMConvertBaseWindowController?
  151. // if (type == .word) { /// Word
  152. // windowController = KMConvertWordWindowController()
  153. // } else if (type == .excel) {
  154. // windowController = KMConvertExcelWindowController()
  155. // } else if (type == .ppt || type == .rtf || type == .html || type == .text) {
  156. // windowController = KMConvertPPTsWindowController()
  157. // if (type == .ppt) {
  158. // windowController?.subType = 1
  159. // } else if (type == .rtf) {
  160. // windowController?.subType = 2
  161. // } else if (type == .html) {
  162. // windowController?.subType = 3
  163. // } else if (type == .text) {
  164. // windowController?.subType = 4
  165. // }
  166. // } else if (type == .csv) {
  167. // windowController = KMConvertCSVWindowController()
  168. // } else if (type == .image) {
  169. // windowController = KMConvertImageWindowController()
  170. // }
  171. // windowController?.subscribeWaterMarkType = type.toSubscribeWaterMarkType()
  172. //
  173. // let model = KMDocumentModel(url: url)
  174. // if (password != nil) {
  175. // let _ = model.unlock(password!)
  176. // }
  177. // windowController?.documentModel = model
  178. //
  179. // windowController?.itemClick = { [weak self] _ in
  180. // self?.km_endSheet()
  181. // }
  182. //
  183. // self.km_safe_beginSheet(windowC: windowController)
  184. }
  185. fileprivate func _showSecurityWindow(url: URL, password: String?, limit: Bool = false) { // 安全
  186. // let windowC = KMSecureEncryptWindowController(windowNibName: "KMSecureEncryptWindowController")
  187. // windowC.documentURL = url
  188. // windowC.myDocument = CPDFDocument(url: url)
  189. // if let _password = password {
  190. // windowC.myDocument.unlock(withPassword: _password)
  191. // }
  192. //
  193. // let newDocument: CPDFDocument = CPDFDocument(url: url)
  194. // windowC.itemClick = { [weak self] _ in
  195. // self?.km_endSheet()
  196. // }
  197. //
  198. // windowC.resultCallback = { [weak self] _ in
  199. // let windowController_secure: KMSecureEncryptWindowController = self?.kmCurrentWindowC as! KMSecureEncryptWindowController
  200. // self?.km_endSheet()
  201. // if let _password = password {
  202. // newDocument.unlock(withPassword: _password)
  203. // }
  204. //
  205. // if (!limit) {
  206. // newDocument.setPasswordOptions(windowController_secure.options)
  207. // let result = KMPasswordInputWindow.saveDocument(newDocument)
  208. // if result {
  209. // NSWorkspace.shared.activateFileViewerSelecting([newDocument.documentURL])
  210. // } else {
  211. // let alert = NSAlert()
  212. // alert.messageText = NSLocalizedString("Failure", comment: "")
  213. // alert.runModal()
  214. // }
  215. // return
  216. // }
  217. //
  218. // NSPanel.savePanel((self?.view.window)!, panel: { panel in
  219. // panel.nameFieldStringValue = url.lastPathComponent
  220. // }) { response, saveUrl in
  221. // if (response == .cancel) {
  222. // return
  223. // }
  224. //
  225. // if let fileUrl = KMTools.saveWatermarkDocument(document: newDocument, to: saveUrl!, secureOptions: windowController_secure.options) {
  226. // NSWorkspace.shared.activateFileViewerSelecting([fileUrl])
  227. // } else {
  228. // let alert = NSAlert()
  229. // alert.messageText = NSLocalizedString("Failure", comment: "")
  230. // alert.runModal()
  231. // }
  232. // }
  233. // }
  234. //
  235. // self.km_beginSheet(windowC: windowC)
  236. }
  237. }
  238. // MARK: - NSSplitViewDelegate
  239. extension KMHomeViewController: NSSplitViewDelegate {
  240. func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  241. return 270.0
  242. }
  243. func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  244. return 270.0
  245. }
  246. func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
  247. return false
  248. }
  249. func splitViewDidResizeSubviews(_ notification: Notification) {
  250. let rect = self.homeSplitView.frame
  251. self.leftBox.setFrameSize(CGSize(width: 270, height: rect.size.height))
  252. self.rightBox.frame = CGRect(origin: CGPoint(x: 271.0, y: 0), size: CGSize(width: rect.width - 271.0, height: rect.height))
  253. }
  254. func splitView(_ splitView: NSSplitView, constrainSplitPosition proposedPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
  255. return proposedPosition
  256. }
  257. func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
  258. return false
  259. }
  260. func splitView(_ splitView: NSSplitView, shouldCollapseSubview subview: NSView, forDoubleClickOnDividerAt dividerIndex: Int) -> Bool {
  261. return false
  262. }
  263. func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
  264. return splitView.isEqual(to: self.homeSplitView)
  265. }
  266. func splitView(_ splitView: NSSplitView, effectiveRect proposedEffectiveRect: NSRect, forDrawnRect drawnRect: NSRect, ofDividerAt dividerIndex: Int) -> NSRect {
  267. return proposedEffectiveRect
  268. }
  269. func splitView(_ splitView: NSSplitView, additionalEffectiveRectOfDividerAt dividerIndex: Int) -> NSRect {
  270. return NSMakeRect(0, 0, 0, 0)
  271. }
  272. }
  273. // MARK: - KMHomeFastToolViewControllerDelegate
  274. extension KMHomeViewController: KMHomeFastToolViewControllerDelegate {
  275. func fastToolViewController(_ viewController: KMHomeFastToolViewController, foldChangeState: Bool) {
  276. if foldChangeState {
  277. rightTopBoxHeightConstraint.constant = 230.0 + ScrollerViewWidget
  278. } else {
  279. rightTopBoxHeightConstraint.constant = 326.0 + ScrollerViewWidget
  280. }
  281. }
  282. func fastToolDidSelectAllTools(_ viewController: KMHomeFastToolViewController) {
  283. fastToolDidSelectAllTools()
  284. }
  285. func fastToolViewController(_ viewController: KMHomeFastToolViewController, didSelectItemsAt indexPaths: [Int]) {
  286. for index in indexPaths {
  287. fastToolItemAction(DataNavigationViewButtonActionType(rawValue: index) ?? .Batch)
  288. }
  289. }
  290. }
  291. // MARK: - KMHomeHistoryFileViewControllerDelegate
  292. extension KMHomeViewController: KMHomeHistoryFileViewControllerDelegate {
  293. func historyFileViewController(_ viewController: KMHomeHistoryFileViewController, deleteDocuments indexPaths: [URL]) {
  294. historyFile(deleteDocuments: indexPaths)
  295. }
  296. func historyFileViewController(_ viewController: KMHomeHistoryFileViewController, didSelectItemsAt indexPaths: [URL]) {
  297. for url in indexPaths {
  298. openHistoryFilePath(url: url)
  299. }
  300. }
  301. func historyFileViewController(_ viewController: KMHomeHistoryFileViewController, refreshLayout refresh: Bool) {
  302. self.refreshScrollView()
  303. }
  304. }
  305. // MARK: - KMPDFToolsViewControllerDelegate
  306. extension KMHomeViewController: KMPDFToolsViewControllerDelegate {
  307. func pdfToolsViewController(_ viewController: KMPDFToolsViewController, didSelectItemsAt indexPaths: [Int]) {
  308. for index in indexPaths {
  309. fastToolItemAction(DataNavigationViewButtonActionType(rawValue: index) ?? .Batch)
  310. }
  311. }
  312. }
  313. // MARK: - KMHomeDragViewDelegate
  314. extension KMHomeViewController: KMHomeDragViewDelegate {
  315. func homeDragView(_ viewController: KMHomeDragView, filePath: URL) {
  316. if self.aiHomeState == .AITranslation {
  317. self.aiTranslation(withFilePath: filePath.path)
  318. } else {
  319. self.openFile(withFilePath: filePath)
  320. }
  321. }
  322. func homeDragView(_ viewController: KMHomeDragView, notSupport: Bool) {
  323. // if notSupport {
  324. // let alert = NSAlert()
  325. // alert.alertStyle = .critical
  326. // alert.messageText = NSLocalizedString("This file format is not supported. Please enter PDF, picture, or Office file", comment: "")
  327. // alert.runModal()
  328. // }
  329. }
  330. }