KMLeftSideViewController+Snapshot.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. //
  2. // KMLeftSideViewController+Snapshot.swift
  3. // PDF Master
  4. //
  5. // Created by tangchao on 2024/1/12.
  6. //
  7. import Foundation
  8. extension KMLeftSideViewController.Key {
  9. static let snapshotSizeScaling = "KMSnapshotSizeScalingKey"
  10. }
  11. // MARK: - Actions
  12. extension KMLeftSideViewController {
  13. @objc func menuItemClick_ExportPNG(_ sender: AnyObject?) {
  14. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  15. return
  16. }
  17. let image = snapshot.thumbnailWithSize(0)
  18. NSPanel.savePanel_data_success(self.view.window!, imageData: image?.pngData(), allowedTypes: ["png"]) { url in
  19. NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "")
  20. }
  21. }
  22. @objc func menuItemClick_ExportJPG(_ sender: AnyObject?) {
  23. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  24. return
  25. }
  26. let image = snapshot.thumbnailWithSize(0)
  27. NSPanel.savePanel_data_success(self.view.window!, imageData: image?.jpgData(), allowedTypes: ["jpg"]) { url in
  28. NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "")
  29. }
  30. }
  31. @objc func menuItemClick_ExportPDF(_ sender: AnyObject?) {
  32. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  33. return
  34. }
  35. if let image = snapshot.thumbnailWithSize(0) {
  36. let document = CPDFDocument()
  37. _ = document?.km_insert(image: image, at: 0)
  38. NSPanel.savePanel_pdf_success(self.view.window!, document: document) { url in
  39. NSWorkspace.shared.selectFile(url.path, inFileViewerRootedAtPath: "")
  40. }
  41. }
  42. }
  43. @objc func menuItemClick_Print(_ sender: AnyObject?) {
  44. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  45. return
  46. }
  47. if let image = snapshot.thumbnailWithSize(0) {
  48. self.delegate?.controller?(controller: self, itemClick: nil, itemKey: .print, params: image)
  49. }
  50. }
  51. @objc func menuItemClick_SelectAll(_ sender: AnyObject?) {
  52. let selected = self.snapshotListIsAllSelected()
  53. for model in self.snapshots {
  54. model.isSelected = !selected
  55. }
  56. Task { @MainActor in
  57. self.snapshotTableView.reloadData()
  58. }
  59. }
  60. @objc func deleteAllSnapshot(_ sender: AnyObject?) {
  61. for model in self.snapshots {
  62. model.windowC?.close()
  63. }
  64. }
  65. @objc func hideSnapshot(_ sender: AnyObject?) {
  66. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  67. return
  68. }
  69. if let data = snapshot.window?.isVisible, data {
  70. snapshot.miniaturize()
  71. }
  72. }
  73. @objc func showSnapshot(_ sender: AnyObject?) {
  74. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  75. return
  76. }
  77. if let data = snapshot.window?.isVisible, data {
  78. snapshot.window?.orderFront(nil)
  79. } else {
  80. snapshot.deminiaturize()
  81. }
  82. }
  83. @objc func deleteSnapshot(_ sender: AnyObject?) {
  84. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  85. return
  86. }
  87. snapshot.close()
  88. }
  89. @objc func menuItemClick_Copy(_ sender: AnyObject?) {
  90. guard let snapshot = (sender as? NSMenuItem)?.representedObject as? KMSnapshotWindowController else {
  91. return
  92. }
  93. let image = snapshot.thumbnailWithSize(0)
  94. if let tiffData = image?.tiffRepresentation {
  95. let pasteboardItem = NSPasteboardItem()
  96. pasteboardItem.setData(tiffData, forType: .tiff)
  97. let pboard = NSPasteboard.general
  98. pboard.clearContents()
  99. pboard.writeObjects([pasteboardItem])
  100. }
  101. }
  102. func snapshot_initSubViews() {
  103. self.snapshotNormalZoomInButton.target = self
  104. self.snapshotNormalZoomInButton.tag = 2
  105. self.snapshotNormalZoomInButton.action = #selector(thumbnailSizeScaling)
  106. self.snapshotNormalZoomOutButton.target = self
  107. self.snapshotNormalZoomOutButton.tag = 3
  108. self.snapshotNormalZoomOutButton.action = #selector(thumbnailSizeScaling)
  109. self.snapshotNormalMoreButton.target = self
  110. self.snapshotNormalMoreButton.tag = 300
  111. self.snapshotNormalMoreButton.action = #selector(leftSideViewMoreButtonAction)
  112. self.snapshotSearchZoomInButton.target = self
  113. self.snapshotSearchZoomInButton.tag = 2
  114. self.snapshotSearchZoomInButton.action = #selector(thumbnailSizeScaling)
  115. self.snapshotSearchZoomOutButton.target = self
  116. self.snapshotSearchZoomOutButton.tag = 3
  117. self.snapshotSearchZoomOutButton.action = #selector(thumbnailSizeScaling)
  118. self.snapshotDoneButton.target = self
  119. self.snapshotDoneButton.tag = 312
  120. self.snapshotDoneButton.action = #selector(leftSideViewDoneButtonAction)
  121. self.snapshotTableView.delegate = self
  122. self.snapshotTableView.dataSource = self
  123. self.snapshotTableView.menu = NSMenu()
  124. self.snapshotTableView.menu?.delegate = self
  125. self.snapshotTableView.doubleAction = #selector(toggleSelectedSnapshots)
  126. self.snapshotTableView.target = self
  127. self.snapshotTableView.botaDelegate = self
  128. self.snapshotTableView.setDraggingSourceOperationMask(.every, forLocal: false)
  129. self.snapshotSearchField.changeCallBack = { [weak self] changeContent in
  130. var editContent = ""
  131. if changeContent != nil {
  132. editContent = changeContent!
  133. }
  134. self?.searchFieldChangeAction(editContent)
  135. }
  136. }
  137. func snapshot_initDefalutValue() {
  138. self.snapshotNormalView.wantsLayer = true
  139. self.snapshotNormalView.layer?.backgroundColor = KMAppearance.Layout.l0Color().cgColor
  140. self.snapshotLabel.stringValue = KMLocalizedString("Snapshots", nil)
  141. self.snapshotLabel.textColor = KMAppearance.Layout.h0Color()
  142. self.snapshotNormalSearchButton.toolTip = KMLocalizedString("Search", nil)
  143. self.snapshotSearchField.backgroundColor = KMAppearance.Layout.l_1Color()
  144. self.snapshotSearchField.wantsLayer = true
  145. self.snapshotSearchField.layer?.backgroundColor = KMAppearance.Layout.l_1Color().cgColor
  146. self.snapshotSearchField.layer?.borderWidth = 1.0
  147. self.snapshotSearchField.layer?.borderColor = KMAppearance.Interactive.a0Color().cgColor
  148. self.snapshotDoneButton.toolTip = KMLocalizedString("Done", nil)
  149. self.snapshotDoneButton.wantsLayer = true
  150. self.snapshotDoneButton.layer?.backgroundColor = KMAppearance.Interactive.a0Color().cgColor
  151. self.snapshotDoneButton.layer?.cornerRadius = 4.0
  152. self.snapshotDoneButton.title = KMLocalizedString("Done", nil)
  153. self.snapshotDoneButton.setTitleColor(KMAppearance.Layout.w0Color())
  154. self.snapshotDoneButton.isHidden = true
  155. self.snapshotSearchField.isHidden = true
  156. self.snapshotSearchZoomOutButton.isHidden = true
  157. self.snapshotSearchZoomInButton.isHidden = true
  158. self.snapshotNormalZoomInButton.toolTip = KMLocalizedString("Zoom In", nil)
  159. self.snapshotSearchZoomInButton.toolTip = KMLocalizedString("Zoom In", nil)
  160. self.snapshotNormalZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil)
  161. self.snapshotSearchZoomOutButton.toolTip = KMLocalizedString("Zoom Out", nil)
  162. self.snapshotTableView.backgroundColor = KMAppearance.Layout.l0Color()
  163. // self.snapshotTableView.backgroundColor = .clear
  164. }
  165. func updataLeftSideSnapView() {
  166. if (snapshots.count < 1) {
  167. self.snapshotNormalSearchButton.isEnabled = false
  168. self.snapshotNormalZoomOutButton.isEnabled = false
  169. self.snapshotNormalZoomInButton.isEnabled = false
  170. self.snapshotNormalMoreButton.isEnabled = false
  171. self.leftSideEmptyVC.deleteSnapBtn.isEnabled = false
  172. self.leftSideEmptyVC.exportSnapBtn.isEnabled = false
  173. self.leftSideEmptyVC.printSnapBtn.isEnabled = false
  174. self.snapshotTableView.usesAlternatingRowBackgroundColors = false
  175. let view = self.snapshotTableView.enclosingScrollView
  176. let viewSize = view?.frame.size ?? .zero
  177. let emptyVcSize = self.leftSideEmptyVC.emptySnapView.frame.size
  178. self.leftSideEmptyVC.emptySnapView.frame = NSMakeRect((viewSize.width-emptyVcSize.width)/2.0,(viewSize.height-emptyVcSize.height)/2.0, emptyVcSize.width, emptyVcSize.height);
  179. self.leftSideEmptyVC.emptySnapView.autoresizingMask = [.minXMargin, .maxXMargin, .minYMargin, .maxYMargin]
  180. self.snapshotTableView.enclosingScrollView?.documentView?.addSubview(self.leftSideEmptyVC.emptySnapView)
  181. } else {
  182. self.snapshotNormalSearchButton.isEnabled = true
  183. self.snapshotNormalZoomOutButton.isEnabled = true
  184. self.snapshotNormalZoomInButton.isEnabled = true
  185. self.snapshotNormalMoreButton.isEnabled = true
  186. self.leftSideEmptyVC.emptySnapView.removeFromSuperview()
  187. self.leftSideEmptyVC.deleteSnapBtn.isEnabled = true
  188. self.leftSideEmptyVC.exportSnapBtn.isEnabled = true
  189. self.leftSideEmptyVC.printSnapBtn.isEnabled = true
  190. }
  191. }
  192. @IBAction func snapshotNormalSearchButtonAction(_ sender: NSButton) {
  193. self.snapshotSearchField.isHidden = false
  194. self.snapshotSearchZoomInButton.isHidden = true
  195. self.snapshotNormalSearchButton.isHidden = true
  196. self.snapshotDoneButton.isHidden = false
  197. self.snapshotLabel.isHidden = true
  198. self.snapshotNormalZoomOutButton.isHidden = true
  199. self.snapshotNormalZoomInButton.isHidden = true
  200. self.snapshotSearchField.becomeFirstResponder()
  201. }
  202. }
  203. extension KMLeftSideViewController {
  204. public func refreshUIOfSnapshotIfNeed(preference: Bool = false) {
  205. if self.type.methodType != .snapshot {
  206. return
  207. }
  208. if preference {
  209. self.reloadSnapshotSize()
  210. }
  211. Task { @MainActor in
  212. self.snapshotTableView.reloadData()
  213. }
  214. }
  215. public func reloadSnapshotDataIfNeed() {
  216. if self.type.methodType != .snapshot {
  217. return
  218. }
  219. Task { @MainActor in
  220. self.snapshotTableView.reloadData()
  221. }
  222. }
  223. public func reloadSnapshotSize() {
  224. let defaultSize = roundf(KMPreference.shared.thumbSnapshotSize)
  225. var thumbnailSize = Self.kTinySize
  226. if defaultSize < Self.kTinySize + Self.kFudgeSize {
  227. } else {
  228. if defaultSize < Self.kSmallSize + Self.kFudgeSize {
  229. thumbnailSize = Self.kSmallSize
  230. } else {
  231. if defaultSize < Self.kLargeSize + Self.kFudgeSize {
  232. thumbnailSize = Self.kLargeSize
  233. } else {
  234. thumbnailSize = Self.kHugeSize
  235. }
  236. }
  237. }
  238. if (abs(thumbnailSize - Float(self.snapshotCacheSize)) > Self.kFudgeSize) {
  239. self.snapshotCacheSize = thumbnailSize.cgFloat
  240. }
  241. Task { @MainActor in
  242. self.snapshotTableView.reloadData()
  243. }
  244. }
  245. func updateSnapshotsIfNeed(for page: CPDFPage?) {
  246. if self.type.methodType != .snapshot {
  247. return
  248. }
  249. if page != nil {
  250. for model in self.snapshots {
  251. if let wc = model.windowC, wc.isPageVisible(page) {
  252. self.snapshotNeedsUpdate(wc)
  253. wc.redisplay()
  254. }
  255. }
  256. } else {
  257. for model in self.snapshots {
  258. model.windowC?.redisplay()
  259. }
  260. self.allSnapshotsNeedUpdate()
  261. }
  262. }
  263. func snapshotNeedsUpdate(_ dirtySnapshot: KMSnapshotWindowController) {
  264. if self.dirtySnapshots.contains(dirtySnapshot) == false {
  265. self.dirtySnapshots.append(dirtySnapshot)
  266. self.updateSnapshotsIfNeeded()
  267. }
  268. }
  269. func updateSnapshotsIfNeeded() {
  270. // if ([rightSideController.snapshotTableView window] != nil && [dirtySnapshots count] > 0 && snapshotTimer == nil)
  271. // snapshotTimer = [[NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:@selector(updateSnapshot:) userInfo:NULL repeats:YES] retain];
  272. }
  273. func allSnapshotsNeedUpdate() {
  274. self.dirtySnapshots.removeAll()
  275. for model in self.snapshots {
  276. if let winC = model.windowC {
  277. self.dirtySnapshots.append(winC)
  278. }
  279. }
  280. self.updateSnapshotsIfNeeded()
  281. }
  282. }
  283. extension KMLeftSideViewController: KMSnapshotWindowControllerDelegate {
  284. func snapshotControllerWillClose(_ controller: KMSnapshotWindowController) {
  285. var flag: KMSnapshotModel?
  286. for model in self.snapshots {
  287. if controller.isEqual(model.windowC) {
  288. flag = model
  289. }
  290. }
  291. if flag != nil {
  292. self.snapshots.removeObject(flag!)
  293. Task { @MainActor in
  294. self.snapshotTableView.reloadData()
  295. self.updataLeftSideSnapView()
  296. }
  297. }
  298. }
  299. func snapshotControllerDidFinishSetup(_ controller: KMSnapshotWindowController) {
  300. let image = controller.thumbnailWithSize(self.snapshotCacheSize)
  301. controller.thumbnail = image
  302. let model = KMSnapshotModel()
  303. model.windowC = controller
  304. self.snapshots.append(model)
  305. Task { @MainActor in
  306. self.snapshotTableView.ks_reloadData()
  307. }
  308. }
  309. func snapshotController(_ controller: KMSnapshotWindowController, miniaturizedRect isMiniaturize: Bool) -> NSRect {
  310. var row = NSNotFound
  311. for (i,sp) in self.snapshots.enumerated() {
  312. if controller.isEqual(sp.windowC) {
  313. row = i
  314. }
  315. }
  316. var rect: NSRect = .zero
  317. if (row != NSNotFound) {
  318. rect = self.snapshotTableView.frameOfCell(atColumn: 0, row: row)
  319. } else {
  320. rect.origin = KMBottomLeftPoint(self.snapshotTableView.visibleRect)
  321. rect.size.width = 1.0
  322. rect.size.height = 1.0
  323. }
  324. rect = self.snapshotTableView.convertRectToScreen(rect)
  325. return rect
  326. }
  327. }