KMNPopOperationViewController.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. //
  2. // KMNPopOperationWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by 丁林圭 on 2024/12/12.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. @objc public enum OperationType: Int, CaseIterable{
  10. case crop = 0
  11. case ocr
  12. case operationNone
  13. }
  14. typealias OperaCropCallback = () -> ()
  15. typealias KMNPopOperationWindowControllerOCRAction = () -> ()
  16. class KMNPopOperationViewController: KMNBaseViewController {
  17. @IBOutlet weak var contentBox: NSBox!
  18. @IBOutlet weak var operationBox: NSBox!
  19. @IBOutlet weak var operationWidthConstraint: NSLayoutConstraint!
  20. @IBOutlet var cropView: NSView!
  21. @IBOutlet var closeButton: ComponentButton!
  22. @IBOutlet var printButton: ComponentButton!
  23. @IBOutlet var extractSelect: ComponentCSelector!
  24. @IBOutlet var resetButton: ComponentButton!
  25. @IBOutlet var addButton: ComponentButton!
  26. @IBOutlet var ocrView: NSView!
  27. @IBOutlet var cancelButton: ComponentButton!
  28. @IBOutlet var ocrButton: ComponentButton!
  29. @IBOutlet weak var cancelWidthConstraint: NSLayoutConstraint!
  30. @IBOutlet weak var ocrWidthConstraint: NSLayoutConstraint!
  31. private var extractGroupView: ComponentGroup?
  32. static let shared: KMNPopOperationViewController = {
  33. let windowC = KMNPopOperationViewController(nibName: "KMNPopOperationViewController", bundle: nil)
  34. return windowC
  35. }()
  36. var cropCurrentCallback: OperaCropCallback?
  37. var updatePDFViewCallback: UpdatePDFViewCallback?
  38. var OCRAction: KMNPopOperationWindowControllerOCRAction?
  39. weak var listView:CPDFListView?
  40. public var popType:OperationType = .operationNone {
  41. didSet {
  42. switch popType {
  43. case .ocr :
  44. ocrView.layoutSubtreeIfNeeded()
  45. operationWidthConstraint.constant = ocrView.bounds.width
  46. self.view.display() //需刷新约束才会有值,不然会变化
  47. operationBox.contentView = ocrView
  48. break
  49. case .crop:
  50. cropView.layoutSubtreeIfNeeded()
  51. operationWidthConstraint.constant = cropView.bounds.width
  52. self.view.display() //需刷新约束才会有值,不然会变化
  53. operationBox.contentView = cropView
  54. break
  55. case .operationNone:
  56. break
  57. }
  58. }
  59. }
  60. override func viewDidLoad() {
  61. super.viewDidLoad()
  62. }
  63. override func initContentView() {
  64. super.initContentView()
  65. extractSelect.properties = ComponentCSelectorProperty(iconImage:NSImage(named: "KMNImageNameListViewCropExport"))
  66. extractSelect.setTarget(self, action: #selector(extractButtonClicked(_ :)))
  67. closeButton.properties = ComponentButtonProperty(type: .text_gray,
  68. size: .s,
  69. state: .normal,
  70. onlyIcon: true,
  71. icon:NSImage(named: "KMNImageNameListViewCropClose"),
  72. keepPressState: false)
  73. closeButton.setTarget(self, action: #selector(closeButtonClicked(_ :)))
  74. printButton.properties = ComponentButtonProperty(type: .text_gray,
  75. size: .s,
  76. state: .normal,
  77. onlyIcon: true,
  78. icon:NSImage(named: "KMNImageNameListViewCropPrint"),
  79. keepPressState: false)
  80. printButton.setTarget(self, action: #selector(printButtonClicked(_ :)))
  81. addButton.properties = ComponentButtonProperty(type: .text_gray,
  82. size: .s,
  83. state: .normal,
  84. onlyIcon: true,
  85. icon:NSImage(named: "KMNImageNameListViewCropAdd"),keepPressState: false)
  86. addButton.setTarget(self, action: #selector(addButtonClicked(_ :)))
  87. resetButton.properties = ComponentButtonProperty(type: .text_gray,
  88. size: .s,
  89. state: .normal,
  90. onlyIcon: true,
  91. icon:NSImage(named: "KMNImageNameListViewCropRest"),
  92. keepPressState: false)
  93. resetButton.setTarget(self, action: #selector(restButtonClicked(_ :)))
  94. }
  95. override func updateUIThemeColor() {
  96. super.updateUIThemeColor()
  97. contentBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/popup")
  98. contentBox.borderColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/3-default")
  99. }
  100. override func updateUILanguage() {
  101. super.updateUILanguage()
  102. cancelButton.properties = ComponentButtonProperty(type: .default_tertiary,
  103. size: .s,
  104. state: .normal,
  105. buttonText: KMLocalizedString("Cancel"))
  106. cancelButton.setTarget(self, action: #selector(cancelButtonClicked(_ :)))
  107. ocrButton.properties = ComponentButtonProperty(type: .primary,
  108. size: .s,
  109. state: .normal,
  110. buttonText: KMLocalizedString("OCR"),
  111. keepPressState: false)
  112. ocrButton.setTarget(self, action: #selector(ocrButtonClicked(_ :)))
  113. ocrWidthConstraint.constant = ocrButton.properties.propertyInfo.viewWidth
  114. cancelWidthConstraint.constant = cancelButton.properties.propertyInfo.viewWidth
  115. }
  116. func removeGroupView() {
  117. if extractGroupView != nil {
  118. extractGroupView?.removeFromSuperview()
  119. }
  120. extractSelect.properties.state = .normal
  121. extractSelect.reloadData()
  122. }
  123. //MARK: - Action
  124. @objc func cancelButtonClicked(_ sender: NSView) {
  125. listView?.selectionRect = NSZeroRect
  126. listView?.selectionPageIndex = UInt(NSNotFound)
  127. updatePDFViewCallback?()
  128. }
  129. @objc func ocrButtonClicked(_ sender: NSView) {
  130. OCRAction?()
  131. }
  132. @objc func addButtonClicked(_ sender: NSView) {
  133. let rect = NSIntegralRect(listView?.currentSelectionRect() ?? CGRect.zero)
  134. let orgPage : CPDFPage = listView?.currentSelectionPage() ?? CPDFPage()
  135. if let page : CPDFPage = orgPage.copy() as? CPDFPage {
  136. page.setBounds(rect, for: .cropBox)
  137. let image = page.thumbnail(of: rect.size) ?? NSImage()
  138. let data = image.tiffRepresentation
  139. let imageItem = NSPasteboardItem()
  140. imageItem.setData(data ?? Data(), forType: .tiff)
  141. let pboard = NSPasteboard.general
  142. pboard.clearContents()
  143. pboard.writeObjects([imageItem])
  144. let point = self.view.window?.frame.origin ?? CGPoint.zero
  145. let height = self.view.frame.height
  146. let width = self.view.frame.width
  147. let listP = self.listView?.window?.frame.origin ?? CGPoint.zero
  148. let pp = CGPoint(x: point.x - listP.x - width - 90, y: point.y - listP.y + height + 25)
  149. _ = KMNCustomAlertView.alertView(message: KMLocalizedString("Copied"), type: .normal_custom, fromView: listView ?? self.view, point: pp)
  150. }
  151. }
  152. @objc func printButtonClicked(_ sender: NSView) {
  153. let rect = listView?.currentSelectionRect() ?? CGRect.zero
  154. let page = listView?.currentPage()
  155. if page != nil {
  156. let copyPage : CPDFPage = page!.copy() as! CPDFPage
  157. copyPage.setBounds(rect, for: .cropBox)
  158. let image : NSImage = copyPage.thumbnail(of:(copyPage.bounds(for: .cropBox)).size)
  159. KMPrintWindowController.printImage(image: image)
  160. }
  161. }
  162. @objc func restButtonClicked(_ sender: NSView) {
  163. cropCurrentCallback?()
  164. }
  165. @objc func extractButtonClicked(_ sender: NSView) {
  166. if extractGroupView?.superview != nil {
  167. removeGroupView()
  168. } else {
  169. var viewHeight: CGFloat = 8
  170. var menuItemArr: [ComponentMenuitemProperty] = []
  171. for i in ["jpg", "png", "pdf"] {
  172. let properties_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  173. itemSelected: false,
  174. isDisabled: false,
  175. keyEquivalent: nil,
  176. text: KMLocalizedString(i))
  177. menuItemArr.append(properties_Menuitem)
  178. viewHeight += 36
  179. }
  180. if extractGroupView == nil {
  181. extractGroupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
  182. }
  183. extractGroupView?.groupDelegate = self
  184. extractGroupView?.frame = CGRectMake(310, 0, 72, viewHeight)
  185. extractGroupView?.updateGroupInfo(menuItemArr)
  186. let point = CGPoint(x: sender.frame.origin.x + sender.frame.size.width/2, y: CGRectGetMinY(sender.frame) - viewHeight)
  187. extractGroupView?.showWithPoint(point, relativeTo: sender)
  188. extractSelect.properties.state = .pressed
  189. extractSelect.reloadData()
  190. }
  191. }
  192. @objc func closeButtonClicked(_ sender: NSView) {
  193. listView?.selectionRect = NSZeroRect
  194. listView?.selectionPageIndex = UInt(NSNotFound)
  195. updatePDFViewCallback?()
  196. }
  197. }
  198. extension KMNPopOperationViewController: ComponentGroupDelegate {
  199. func componentGroupDidDismiss(group: ComponentGroup?) {
  200. removeGroupView()
  201. extractSelect.properties.state = .normal
  202. extractSelect.reloadData()
  203. }
  204. func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
  205. if group == extractGroupView {
  206. let rect = NSIntegralRect(listView?.currentSelectionRect() ?? CGRect.zero)
  207. let orgPage : CPDFPage = listView?.currentSelectionPage() ?? CPDFPage()
  208. if let page : CPDFPage = orgPage.copy() as? CPDFPage {
  209. page.setBounds(rect, for: .cropBox)
  210. let image = page.thumbnail(of: rect.size) ?? NSImage()
  211. let data = image.tiffRepresentation
  212. guard let data = data else { return }
  213. let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data) ?? NSBitmapImageRep()
  214. imageRep.size = rect.size
  215. let savePanel = NSSavePanel()
  216. if let selItem = menuItemProperty {
  217. let index = group?.menuItemArr.firstIndex(of: selItem)
  218. if index == 0 {
  219. savePanel.allowedFileTypes = ["jpg"]
  220. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  221. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  222. if (response != .OK) {
  223. return
  224. }
  225. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  226. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  227. }
  228. }
  229. } else if index == 1 {
  230. savePanel.allowedFileTypes = ["png"]
  231. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])!
  232. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  233. if (response != .OK) {
  234. return
  235. }
  236. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  237. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  238. }
  239. }
  240. } else if index == 2 {
  241. savePanel.allowedFileTypes = ["pdf"]
  242. let pdfdocument = CPDFDocument()
  243. let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png")
  244. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  245. if NSData(data: imageData).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) {
  246. pdfdocument?.insertPage(image.size, withImage: signatureImagePath, at: 0)
  247. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  248. if (response != .OK) {
  249. return
  250. }
  251. if pdfdocument!.write(to: savePanel.url!) {
  252. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  253. }
  254. }
  255. }
  256. }
  257. }
  258. }
  259. }
  260. }
  261. }