KMNPopOperationViewController.swift 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  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. ocrButton.setTarget(self, action: #selector(ocrButtonClicked(_ :)))
  112. ocrWidthConstraint.constant = ocrButton.properties.propertyInfo.viewWidth
  113. cancelWidthConstraint.constant = cancelButton.properties.propertyInfo.viewWidth
  114. }
  115. func removeGroupView() {
  116. if extractGroupView != nil {
  117. extractGroupView?.removeFromSuperview()
  118. }
  119. extractSelect.properties.state = .normal
  120. extractSelect.reloadData()
  121. }
  122. //MARK: - Action
  123. @objc func cancelButtonClicked(_ sender: NSView) {
  124. listView?.selectionRect = NSZeroRect
  125. listView?.selectionPageIndex = UInt(NSNotFound)
  126. updatePDFViewCallback?()
  127. }
  128. @objc func ocrButtonClicked(_ sender: NSView) {
  129. OCRAction?()
  130. }
  131. @objc func addButtonClicked(_ sender: NSView) {
  132. let rect = NSIntegralRect(listView?.currentSelectionRect() ?? CGRect.zero)
  133. let orgPage : CPDFPage = listView?.currentSelectionPage() ?? CPDFPage()
  134. if let page : CPDFPage = orgPage.copy() as? CPDFPage {
  135. page.setBounds(rect, for: .cropBox)
  136. let image = page.thumbnail(of: rect.size) ?? NSImage()
  137. let data = image.tiffRepresentation
  138. let imageItem = NSPasteboardItem()
  139. imageItem.setData(data ?? Data(), forType: .tiff)
  140. let pboard = NSPasteboard.general
  141. pboard.clearContents()
  142. pboard.writeObjects([imageItem])
  143. }
  144. }
  145. @objc func printButtonClicked(_ sender: NSView) {
  146. let rect = listView?.currentSelectionRect() ?? CGRect.zero
  147. let page = listView?.currentPage()
  148. if page != nil {
  149. let copyPage : CPDFPage = page!.copy() as! CPDFPage
  150. copyPage.setBounds(rect, for: .cropBox)
  151. let image : NSImage = copyPage.thumbnail(of:(copyPage.bounds(for: .cropBox)).size)
  152. KMPrintWindowController.printImage(image: image)
  153. }
  154. }
  155. @objc func restButtonClicked(_ sender: NSView) {
  156. cropCurrentCallback?()
  157. }
  158. @objc func extractButtonClicked(_ sender: NSView) {
  159. if extractGroupView?.superview != nil {
  160. removeGroupView()
  161. } else {
  162. var viewHeight: CGFloat = 8
  163. var menuItemArr: [ComponentMenuitemProperty] = []
  164. for i in ["jpg", "png", "pdf"] {
  165. let properties_Menuitem: ComponentMenuitemProperty = ComponentMenuitemProperty(multipleSelect: false,
  166. itemSelected: false,
  167. isDisabled: false,
  168. keyEquivalent: nil,
  169. text: KMLocalizedString(i))
  170. menuItemArr.append(properties_Menuitem)
  171. viewHeight += 36
  172. }
  173. if extractGroupView == nil {
  174. extractGroupView = ComponentGroup.createFromNib(in: ComponentLibrary.shared.componentBundle())
  175. }
  176. extractGroupView?.groupDelegate = self
  177. extractGroupView?.frame = CGRectMake(310, 0, 72, viewHeight)
  178. extractGroupView?.updateGroupInfo(menuItemArr)
  179. let point = CGPoint(x: sender.frame.origin.x + sender.frame.size.width/2, y: CGRectGetMinY(sender.frame) - viewHeight)
  180. extractGroupView?.showWithPoint(point, relativeTo: sender)
  181. extractSelect.properties.state = .pressed
  182. extractSelect.reloadData()
  183. }
  184. }
  185. @objc func closeButtonClicked(_ sender: NSView) {
  186. listView?.selectionRect = NSZeroRect
  187. listView?.selectionPageIndex = UInt(NSNotFound)
  188. updatePDFViewCallback?()
  189. }
  190. }
  191. extension KMNPopOperationViewController: ComponentGroupDelegate {
  192. func componentGroupDidDismiss(group: ComponentGroup?) {
  193. removeGroupView()
  194. extractSelect.properties.state = .normal
  195. extractSelect.reloadData()
  196. }
  197. func componentGroupDidSelect(group: ComponentGroup?, menuItemProperty: ComponentMenuitemProperty?) {
  198. if group == extractGroupView {
  199. let rect = NSIntegralRect(listView?.currentSelectionRect() ?? CGRect.zero)
  200. let orgPage : CPDFPage = listView?.currentSelectionPage() ?? CPDFPage()
  201. if let page : CPDFPage = orgPage.copy() as? CPDFPage {
  202. page.setBounds(rect, for: .cropBox)
  203. let image = page.thumbnail(of: rect.size) ?? NSImage()
  204. let data = image.tiffRepresentation
  205. guard let data = data else { return }
  206. let imageRep : NSBitmapImageRep = NSBitmapImageRep(data: data) ?? NSBitmapImageRep()
  207. imageRep.size = rect.size
  208. let savePanel = NSSavePanel()
  209. if let selItem = menuItemProperty {
  210. let index = group?.menuItemArr.firstIndex(of: selItem)
  211. if index == 0 {
  212. savePanel.allowedFileTypes = ["jpg"]
  213. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  214. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  215. if (response != .OK) {
  216. return
  217. }
  218. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  219. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  220. }
  221. }
  222. } else if index == 1 {
  223. savePanel.allowedFileTypes = ["png"]
  224. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.png, properties: [:])!
  225. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  226. if (response != .OK) {
  227. return
  228. }
  229. if NSData(data: imageData).write(to: savePanel.url!, atomically: true) {
  230. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  231. }
  232. }
  233. } else if index == 2 {
  234. savePanel.allowedFileTypes = ["pdf"]
  235. let pdfdocument = CPDFDocument()
  236. let signatureImagePath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).first?.stringByAppendingPathComponent("signatureImage.png")
  237. let imageData : Data = imageRep.representation(using: NSBitmapImageRep.FileType.jpeg, properties: [:])!
  238. if NSData(data: imageData).write(to: URL(fileURLWithPath: signatureImagePath!), atomically: true) {
  239. pdfdocument?.insertPage(image.size, withImage: signatureImagePath, at: 0)
  240. savePanel.beginSheetModal(for: listView?.window ?? NSWindow()) { response in
  241. if (response != .OK) {
  242. return
  243. }
  244. if pdfdocument!.write(to: savePanel.url!) {
  245. NSWorkspace.shared.selectFile(savePanel.url?.path, inFileViewerRootedAtPath: "");
  246. }
  247. }
  248. }
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }