KMEditPDFPopToolBarController.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. //
  2. // KMEditPDFPopToolBarController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2024/6/18.
  6. //
  7. import Cocoa
  8. @objc enum KMEditPDFToolbarItemKey: Int {
  9. case none
  10. case color
  11. case fontStyle
  12. case fontAdd
  13. case fontReduce
  14. case fontBold
  15. case fontItalic
  16. case textAlignment
  17. case leftRotate
  18. case rightRotate
  19. case reverseX // 左右翻转
  20. case reverseY // 上下翻转
  21. case crop
  22. case replace
  23. case export
  24. case alignmentLeft
  25. case alignmentRight
  26. case alignmentCenterX
  27. case alignmentjustifiedX // 左右两端对齐
  28. case alignmentTop
  29. case alignmentBottom
  30. case alignmentCenterY
  31. case alignmentjustifiedY // 上下两端对齐
  32. case separator // 分割线
  33. }
  34. class KMEditPDFToolbarModel: NSObject {
  35. var itemKey: KMEditPDFToolbarItemKey = .none
  36. var isEnabled = true
  37. var fontName: String?
  38. var state: NSControl.StateValue = .mixed
  39. }
  40. class KMSeparatorLineView: NSView {
  41. var strokeColor: NSColor = .black {
  42. didSet {
  43. self.needsDisplay = true
  44. }
  45. }
  46. override func draw(_ dirtyRect: NSRect) {
  47. super.draw(dirtyRect)
  48. let rect = self.bounds
  49. let ctx = NSGraphicsContext.current?.cgContext
  50. ctx?.saveGState()
  51. ctx?.setLineWidth(1)
  52. ctx?.setStrokeColor(self.strokeColor.cgColor)
  53. let startP = NSPoint(x: rect.size.width*0.5, y: 6+2)
  54. ctx?.move(to: startP)
  55. let endP = NSPoint(x: rect.size.width*0.5, y: rect.size.height-8)
  56. ctx?.addLine(to: endP)
  57. ctx?.strokePath()
  58. ctx?.restoreGState()
  59. }
  60. }
  61. struct KMEditPDFToolbarStyle: OptionSet {
  62. let rawValue: Int
  63. static var text = KMEditPDFToolbarStyle(rawValue: 1 << 0)
  64. static var image = KMEditPDFToolbarStyle(rawValue: 1 << 1)
  65. }
  66. class KMEditPDFPopToolBarController: NSViewController {
  67. deinit {
  68. KMPrint("KMEditPDFPopToolBarController deinit.")
  69. }
  70. convenience init() {
  71. self.init(nibName: "KMEditPDFPopToolBarController", bundle: nil)
  72. }
  73. var toolbarView: KMEditPDFToolbarView?
  74. var itemKeys: [KMEditPDFToolbarItemKey] = [] {
  75. didSet {
  76. // self.toolbarView?.reloadData()
  77. }
  78. }
  79. var datas: [KMEditPDFToolbarModel] = [] {
  80. didSet {
  81. self.toolbarView?.reloadData()
  82. }
  83. }
  84. var fontColor: NSColor?
  85. var fontName: String?
  86. var itemClick: ((KMEditPDFToolbarItemKey, Any?)->Void)?
  87. private weak var popover_: NSPopover?
  88. override func viewDidLoad() {
  89. super.viewDidLoad()
  90. // Do view setup here.
  91. self.interfaceThemeDidChanged(NSApp.appearance?.name ?? .aqua)
  92. let toolbarView = KMEditPDFToolbarView()
  93. self.toolbarView = toolbarView
  94. toolbarView.frame = self.view.bounds
  95. toolbarView.autoresizingMask = [.width, .height]
  96. self.view.addSubview(toolbarView)
  97. toolbarView.delegate = self
  98. toolbarView.inset = .init(top: 6, left: 4, bottom: 0, right: 0)
  99. toolbarView.reloadData()
  100. }
  101. override func viewDidDisappear() {
  102. super.viewDidDisappear()
  103. let itemView = (self.toolbarView?.itemViews.safe_element(for: 1) as? KMEditPDFToolbarItemView)
  104. (itemView?.obj as? KMDesignSelect)?.createFilePopover.close()
  105. self.popover_?.close()
  106. }
  107. @objc func _buttonClick(_ sender: NSButton) {
  108. let idx = sender.tag
  109. if idx >= 0 && idx < self.itemKeys.count {
  110. self.itemClick?(self.itemKeys[idx], nil)
  111. }
  112. }
  113. @objc func textAlignmentItemClick(_ sender: NSButton) {
  114. let vc = KMTextAlignmentController(nibName: "KMTextAlignmentController", bundle: nil)
  115. let createFilePopover: NSPopover = NSPopover.init()
  116. createFilePopover.contentViewController = vc
  117. // createFilePopover.delegate = self
  118. createFilePopover.animates = true
  119. createFilePopover.behavior = .semitransient
  120. createFilePopover.setValue(true, forKey: "shouldHideAnchor")
  121. createFilePopover.show(relativeTo: CGRect(x: sender.bounds.origin.x, y: 20, width: sender.bounds.size.width, height: sender.bounds.size.height), of: sender, preferredEdge: .maxY)
  122. self.popover_ = createFilePopover
  123. vc.itemAction = { [weak self] idx, _ in
  124. var data: NSTextAlignment = .left
  125. if idx == 0 {
  126. data = .left
  127. } else if idx == 1 {
  128. data = .center
  129. } else if idx == 2 {
  130. data = .right
  131. }
  132. self?.itemClick?(.textAlignment, data)
  133. createFilePopover.close()
  134. }
  135. }
  136. @objc func colorPanelAction(_ sender: NSColorPanel) {
  137. let color = sender.color
  138. let colorView = (self.toolbarView?.itemViews.first as? KMEditPDFToolbarItemView)?.view as? KMEditPDFColorView
  139. colorView?.colorBtn.image = nil
  140. colorView?.colorBtn.layer?.backgroundColor = color.cgColor
  141. self.itemClick?(.color, color)
  142. }
  143. override func interfaceThemeDidChanged(_ appearance: NSAppearance.Name) {
  144. super.interfaceThemeDidChanged(appearance)
  145. self.view.wantsLayer = true
  146. if appearance == .darkAqua {
  147. self.view.layer?.backgroundColor = NSColor(red: 37/255.0, green: 37/255.0, blue: 38/255.0, alpha: 1.0).cgColor
  148. } else {
  149. self.view.layer?.backgroundColor = .white
  150. }
  151. Task { @MainActor in
  152. self.toolbarView?.reloadData()
  153. }
  154. }
  155. }
  156. extension KMEditPDFPopToolBarController: KMEditPDFToolbarViewDelegate {
  157. func numberOfItems(in toolbarView: KMEditPDFToolbarView) -> Int {
  158. return self.datas.count
  159. }
  160. func toolbarView(_ toolbarView: KMEditPDFToolbarView, viewFor index: Int) -> NSView? {
  161. let model = self.datas[index]
  162. let itemKey = model.itemKey
  163. if itemKey == .color {
  164. let colorView = KMEditPDFToolbarItemView()
  165. let view = KMEditPDFColorView()
  166. // view.isEnabled = model.isEnabled
  167. if model.isEnabled {
  168. view.colorBtn.layer?.backgroundColor = self.fontColor?.cgColor
  169. } else {
  170. view.colorBtn.layer?.backgroundColor = .clear
  171. view.colorBtn.image = NSImage(named: "KMImageNameEditPDFColorDisabled")
  172. }
  173. view.itemClick = { [weak self] idx, _ in
  174. let panel = NSColorPanel.shared
  175. panel.setTarget(self)
  176. panel.setAction(#selector(self?.colorPanelAction))
  177. panel.orderFront(nil)
  178. }
  179. colorView.view = view
  180. return colorView
  181. } else if itemKey == .fontStyle {
  182. let fontStyleView = KMEditPDFToolbarItemView()
  183. let viewC = KMDesignSelect.init(withType: .Combox)
  184. viewC.isScrollPop = true
  185. fontStyleView.view = viewC.view
  186. fontStyleView.obj = viewC
  187. // if KMAppearance.isDarkMode() {
  188. // viewC.background = NSColor(white: 0, alpha: 0.15)
  189. // }
  190. viewC.borderColor = KMAppearance.Interactive.s0Color()
  191. viewC.background = KMAppearance.Layout.l1Color()
  192. viewC.background_hov = KMAppearance.Layout.l1Color()
  193. viewC.background_focus = KMAppearance.Layout.l1Color()
  194. viewC.textColor = KMAppearance.Layout.h1Color()
  195. viewC.textColor_hov = KMAppearance.Layout.h1Color()
  196. viewC.textColor_focus = KMAppearance.Layout.h1Color()
  197. viewC.popViewControllerBackground = KMAppearance.Layout.bgColor()
  198. viewC.popViewControllerTextColor = KMAppearance.Layout.h0Color()
  199. viewC.popViewControllerEnterFillColor = KMAppearance.Interactive.s0Color()
  200. viewC.updateUI()
  201. let familyNames = CPDFFont.familyNames
  202. viewC.removeAllItems()
  203. viewC.addItems(withObjectValues: familyNames)
  204. if let data = model.fontName {
  205. viewC.stringValue = data
  206. } else {
  207. // viewC.selectItem(at: 0)
  208. viewC.stringValue = "--"
  209. }
  210. viewC.delete = self
  211. return fontStyleView
  212. } else if itemKey == .separator {
  213. let colorView = KMEditPDFToolbarItemView()
  214. let view = KMSeparatorLineView()
  215. view.strokeColor = KMAppearance.separatorLineColor()
  216. colorView.view = view
  217. return colorView
  218. } else if itemKey == .textAlignment {
  219. let colorView = KMEditPDFToolbarItemView()
  220. let viewC = KMDesignButton(withType: .Image)
  221. colorView.view = viewC.view
  222. colorView.obj = viewC
  223. viewC.pagination()
  224. if KMAppearance.isDarkMode() {
  225. viewC.background_hov = NSColor(hex: "#365898")
  226. } else {
  227. // viewC.background_hov = NSColor(hex: "#EDEEF0")
  228. }
  229. viewC.target = self
  230. viewC.action = #selector(textAlignmentItemClick)
  231. viewC.image = NSImage(named: "KMImageNameEditPDFAlignCenterSelect")!
  232. return colorView
  233. }
  234. let colorView = KMEditPDFToolbarItemView()
  235. let viewC = KMDesignButton(withType: .Image)
  236. colorView.view = viewC.view
  237. colorView.obj = viewC
  238. viewC.pagination()
  239. if KMAppearance.isDarkMode() {
  240. viewC.background_hov = NSColor(hex: "#365898")
  241. } else {
  242. // viewC.background_hov = NSColor(hex: "#EDEEF0")
  243. }
  244. viewC.tag = index
  245. viewC.state = model.isEnabled ? .Norm : .Disabled
  246. viewC.button.isEnabled = model.isEnabled
  247. viewC.target = self
  248. viewC.action = #selector(_buttonClick)
  249. viewC.background_disabled = .clear
  250. viewC.borderColor_disabled = .clear
  251. if itemKey == .fontAdd {
  252. viewC.image = NSImage(named: "KMImageNameEditPDFFontAdd")!
  253. viewC.image_disabled = NSImage(named: "KMImageNameEditPDFFontAddDisabled")!
  254. colorView.popToolTip = NSLocalizedString("Larger font size", comment: "")
  255. } else if itemKey == .fontReduce {
  256. viewC.image = NSImage(named: "KMImageNameEditPDFFontReduce")!
  257. viewC.image_disabled = NSImage(named: "KMImageNameEditPDFFontReduceDisabled")!
  258. colorView.popToolTip = NSLocalizedString("Reduce font size", comment: "")
  259. } else if itemKey == .fontBold {
  260. viewC.image = NSImage(named: "KMImageNameEditPDFFontBold")!
  261. colorView.popToolTip = NSLocalizedString("Bold font", comment: "")
  262. // viewC.button.keyEquivalent = "b"
  263. // viewC.button.keyEquivalentModifierMask = [.control]
  264. } else if itemKey == .fontItalic {
  265. viewC.image = NSImage(named: "KMImageNameEditPDFFontItalic")!
  266. colorView.popToolTip = NSLocalizedString("Italic font", comment: "")
  267. } else if itemKey == .textAlignment {
  268. viewC.image = NSImage(named: "KMImageNameEditPDFAlignCenterSelect")!
  269. colorView.popToolTip = NSLocalizedString("Center text", comment: "")
  270. }
  271. // 图片
  272. else if itemKey == .leftRotate {
  273. viewC.image = NSImage(named: "KMImageNameEditPDFLeftRotateNew")!
  274. colorView.popToolTip = NSLocalizedString("Rotate left", comment: "")
  275. } else if itemKey == .rightRotate {
  276. viewC.image = NSImage(named: "KMImageNameEditPDFRightRotateNew")!
  277. colorView.popToolTip = NSLocalizedString("Rotate right", comment: "")
  278. } else if itemKey == .reverseX {
  279. viewC.image = NSImage(named: "KMImageNameEditPDFReverseX")!
  280. colorView.popToolTip = NSLocalizedString("Flip horizontal", comment: "")
  281. } else if itemKey == .reverseY {
  282. viewC.image = NSImage(named: "KMImageNameEditPDFReverseY")!
  283. colorView.popToolTip = NSLocalizedString("Flip vertical", comment: "")
  284. } else if itemKey == .crop {
  285. viewC.image = NSImage(named: "KMImageNameEditPDFCrop")!
  286. viewC.image_disabled = NSImage(named: "KMImageNameEditPDFCropDisabled")!
  287. colorView.popToolTip = NSLocalizedString("Crop", comment: "")
  288. } else if itemKey == .replace {
  289. viewC.image = NSImage(named: "KMImageNameEditPDFReplace")!
  290. viewC.image_disabled = NSImage(named: "KMImageNameEditPDFReplaceDisabled")!
  291. colorView.popToolTip = NSLocalizedString("Replace", comment: "")
  292. } else if itemKey == .export {
  293. viewC.image = NSImage(named: "KMImageNameEditPDFExport")!
  294. colorView.popToolTip = NSLocalizedString("Export file", comment: "")
  295. }
  296. // 对齐
  297. else if itemKey == .alignmentLeft {
  298. viewC.image = NSImage(named: "KMImageNameEditPDFImage45_1")!
  299. colorView.popToolTip = NSLocalizedString("Align left", comment: "")
  300. } else if itemKey == .alignmentCenterX {
  301. viewC.image = NSImage(named: "KMImageNameEditPDFImage46_1")!
  302. colorView.popToolTip = NSLocalizedString("Align center", comment: "")
  303. } else if itemKey == .alignmentRight {
  304. viewC.image = NSImage(named: "KMImageNameEditPDFImage47_1")!
  305. colorView.popToolTip = NSLocalizedString("Align right", comment: "")
  306. } else if itemKey == .alignmentjustifiedX {
  307. viewC.image = NSImage(named: "KMImageNameEditPDFImage21_1")!
  308. viewC._image_disabled = NSImage(named: "KMImageNameEditPDFImage21")!
  309. colorView.popToolTip = NSLocalizedString("Align both ends", comment: "")
  310. } else if itemKey == .alignmentTop {
  311. viewC.image = NSImage(named: "KMImageNameEditPDFImage48_1")!
  312. colorView.popToolTip = NSLocalizedString("Align top", comment: "")
  313. } else if itemKey == .alignmentCenterY {
  314. viewC.image = NSImage(named: "KMImageNameEditPDFImage49_1")!
  315. colorView.popToolTip = NSLocalizedString("Align center in vertical", comment: "")
  316. } else if itemKey == .alignmentBottom {
  317. viewC.image = NSImage(named: "KMImageNameEditPDFImage50_1")!
  318. colorView.popToolTip = NSLocalizedString("Align bottom", comment: "")
  319. } else if itemKey == .alignmentjustifiedY {
  320. viewC.image = NSImage(named: "KMImageNameEditPDFImage20_1")!
  321. viewC._image_disabled = NSImage(named: "KMImageNameEditPDFImage20")!
  322. colorView.popToolTip = NSLocalizedString("Align ends in vertical", comment: "")
  323. }
  324. viewC.updateUI()
  325. return colorView
  326. }
  327. func toolbarView(_ toolbarView: KMEditPDFToolbarView, sizeForItemAt index: Int) -> NSSize {
  328. let itemKey = self.itemKeys[index]
  329. if itemKey == .color {
  330. return NSMakeSize(56, 32)
  331. } else if itemKey == .fontStyle {
  332. return NSMakeSize(148, 32)
  333. } else if itemKey == .separator {
  334. return NSMakeSize(16, 32)
  335. }
  336. return NSMakeSize(32, 32)
  337. }
  338. }
  339. extension KMEditPDFPopToolBarController: KMSelectPopButtonDelegate {
  340. func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) {
  341. self.itemClick?(.fontStyle, obj.stringValue)
  342. }
  343. func km_controlTextDidEndEditing(_ obj: KMDesignSelect) {
  344. }
  345. }