KMEditPDFPopToolBarController.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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 color
  10. case fontStyle
  11. case fontAdd
  12. case fontReduce
  13. case fontBold
  14. case fontItalic
  15. case textAlignment
  16. case leftRotate
  17. case rightRotate
  18. case reverseX // 左右翻转
  19. case reverseY // 上下翻转
  20. case crop
  21. case replace
  22. case export
  23. case alignmentLeft
  24. case alignmentRight
  25. case alignmentCenterX
  26. case alignmentjustifiedX // 左右两端对齐
  27. case alignmentTop
  28. case alignmentBottom
  29. case alignmentCenterY
  30. case alignmentjustifiedY // 上下两端对齐
  31. case separator // 分割线
  32. }
  33. class KMSeparatorLineView: NSView {
  34. var strokeColor: NSColor = .black {
  35. didSet {
  36. self.needsDisplay = true
  37. }
  38. }
  39. override func draw(_ dirtyRect: NSRect) {
  40. super.draw(dirtyRect)
  41. let rect = self.bounds
  42. let ctx = NSGraphicsContext.current?.cgContext
  43. ctx?.saveGState()
  44. ctx?.setLineWidth(1)
  45. ctx?.setStrokeColor(self.strokeColor.cgColor)
  46. let startP = NSPoint(x: rect.size.width*0.5, y: 6+2)
  47. ctx?.move(to: startP)
  48. let endP = NSPoint(x: rect.size.width*0.5, y: rect.size.height-8)
  49. ctx?.addLine(to: endP)
  50. ctx?.strokePath()
  51. ctx?.restoreGState()
  52. }
  53. }
  54. struct KMEditPDFToolbarStyle: OptionSet {
  55. let rawValue: Int
  56. static var text = KMEditPDFToolbarStyle(rawValue: 1 << 0)
  57. static var image = KMEditPDFToolbarStyle(rawValue: 1 << 1)
  58. }
  59. class KMEditPDFToolbarItemView: NSView {
  60. private lazy var contentBox_: NSBox = {
  61. let view = NSBox()
  62. view.boxType = .custom
  63. view.titlePosition = .noTitle
  64. view.contentViewMargins = .zero
  65. view.borderWidth = 0
  66. return view
  67. }()
  68. var view: NSView? {
  69. didSet {
  70. if let data = self.view {
  71. self.contentBox_.contentView = data
  72. }
  73. self.needsLayout = true
  74. }
  75. }
  76. var obj: AnyObject?
  77. convenience init() {
  78. self.init(frame: .zero)
  79. self.addSubview(self.contentBox_)
  80. }
  81. override func layout() {
  82. super.layout()
  83. let height = NSHeight(self.bounds)
  84. let width = NSWidth(self.bounds)
  85. // let boxFrame = self.contentBox_.contentView?.frame ?? .zero
  86. // let boxX = (width - boxFrame.size.width) * 0.5
  87. // let boxY = (height - boxFrame.size.height) * 0.5
  88. // self.contentBox_.frame = NSMakeRect(boxX, boxY, boxFrame.size.width, boxFrame.size.height)
  89. self.contentBox_.frame = self.bounds
  90. // KMPrint("-------- \(boxFrame)")
  91. }
  92. }
  93. class KMEditPDFColorView: NSView {
  94. lazy var box: NSBox = {
  95. let view = NSBox()
  96. view.boxType = .custom
  97. view.titlePosition = .noTitle
  98. view.contentViewMargins = .zero
  99. view.borderWidth = 1
  100. view.cornerRadius = 4
  101. view.borderColor = NSColor(hex: "#DFE1E5")
  102. return view
  103. }()
  104. lazy var colorBtn: NSButton = {
  105. let view = NSButton()
  106. view.isBordered = false
  107. view.title = ""
  108. view.wantsLayer = true
  109. view.layer?.cornerRadius = 10
  110. view.layer?.backgroundColor = .black
  111. view.target = self
  112. view.action = #selector(buttonClick)
  113. return view
  114. }()
  115. lazy var plateBtn: NSButton = {
  116. let view = NSButton()
  117. view.isBordered = false
  118. view.title = ""
  119. view.wantsLayer = true
  120. view.layer?.cornerRadius = 10
  121. view.layer?.masksToBounds = true
  122. view.image = NSImage(named: "view_color")
  123. return view
  124. }()
  125. override init(frame frameRect: NSRect) {
  126. super.init(frame: frameRect)
  127. self.initSubView()
  128. }
  129. required init?(coder: NSCoder) {
  130. super.init(coder: coder)
  131. self.initSubView()
  132. }
  133. convenience init() {
  134. self.init(frame: .init(x: 0, y: 0, width: 56, height: 32))
  135. }
  136. func initSubView() {
  137. self.addSubview(self.box)
  138. self.box.contentView?.addSubview(self.colorBtn)
  139. self.box.contentView?.addSubview(self.plateBtn)
  140. }
  141. override func layout() {
  142. super.layout()
  143. let height = NSHeight(self.bounds)
  144. self.box.frame = self.bounds
  145. let btnWH: CGFloat = 20
  146. let btnY: CGFloat = (height - btnWH) * 0.5
  147. let colorX: CGFloat = 4
  148. self.colorBtn.frame = NSMakeRect(colorX, btnY, btnWH, btnWH)
  149. let plateX: CGFloat = NSMaxX(self.colorBtn.frame) + 8
  150. self.plateBtn.frame = NSMakeRect(plateX, btnY, btnWH, btnWH)
  151. }
  152. @objc func buttonClick(_ sender: NSButton) {
  153. }
  154. }
  155. @objc protocol KMEditPDFToolbarViewDelegate: NSObjectProtocol {
  156. @objc optional func numberOfItems(in toolbarView: KMEditPDFToolbarView) -> Int
  157. @objc optional func toolbarView(_ toolbarView: KMEditPDFToolbarView, viewFor index: Int) -> NSView?
  158. @objc optional func toolbarView(_ toolbarView: KMEditPDFToolbarView, sizeForItemAt index: Int) -> NSSize
  159. // @objc optional func toolbarView(_ toolbarView: KMEditPDFToolbarView, insetForSectionAt section: Int) -> NSEdgeInsets
  160. // @objc optional func toolbarView(_ toolbarView: KMEditPDFToolbarView, minimumLineSpacingForSectionAt section: Int) -> CGFloat
  161. // @objc optional func toolbarView(_ toolbarView: KMEditPDFToolbarView, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
  162. }
  163. class KMEditPDFToolbarView: NSView {
  164. weak var delegate: KMEditPDFToolbarViewDelegate?
  165. convenience init() {
  166. self.init(frame: .zero)
  167. }
  168. var inset: NSEdgeInsets = NSEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) {
  169. didSet {
  170. self.needsLayout = true
  171. }
  172. }
  173. func reloadData() {
  174. for sv in self.subviews {
  175. sv.removeFromSuperview()
  176. }
  177. guard let num = self.delegate?.numberOfItems?(in: self) else {
  178. return
  179. }
  180. for i in 0 ..< num {
  181. if let view = self.delegate?.toolbarView?(self, viewFor: i) {
  182. self.addSubview(view)
  183. }
  184. }
  185. self.needsLayout = true
  186. }
  187. override func layout() {
  188. super.layout()
  189. let height = NSHeight(self.bounds)
  190. let leftMargin = self.inset.left
  191. let topMargin = self.inset.top
  192. var x = leftMargin
  193. let vSpace: CGFloat = 2
  194. for (i, sv) in self.subviews.enumerated() {
  195. if let size = self.delegate?.toolbarView?(self, sizeForItemAt: i) {
  196. let y = topMargin
  197. var frame = NSRect(x: x, y: y, width: size.width, height: size.height)
  198. x += (size.width + vSpace)
  199. sv.frame = frame
  200. }
  201. }
  202. }
  203. }
  204. @objcMembers class KMEditPDFPopToolBarWindow: NSWindow {
  205. static let shared = KMEditPDFPopToolBarWindow()
  206. var style: KMEditPDFToolbarStyle = .text
  207. var isMultiple: Bool = false
  208. var itemClick: ((KMEditPDFToolbarItemKey, Any?)->Void)?
  209. convenience init() {
  210. let rect = NSRect(x: 0, y: 0, width: 400, height: 44)
  211. let styleMask: NSWindow.StyleMask = [.fullSizeContentView]
  212. self.init(contentRect: rect, styleMask: styleMask, backing: .buffered, defer: false)
  213. }
  214. override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
  215. super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag)
  216. let contentViewC = KMEditPDFPopToolBarController()
  217. self.contentViewController = contentViewC
  218. self.titlebarAppearsTransparent = true
  219. self.titleVisibility = .hidden
  220. // self.level = .popUpMenu
  221. // self.isMovableByWindowBackground = false
  222. self.isMovable = false
  223. self.contentView?.wantsLayer = true
  224. self.contentView?.layer?.cornerRadius = 4
  225. self.contentView?.layer?.masksToBounds = true
  226. self.backgroundColor = .clear
  227. contentViewC.itemClick = { [weak self] itemKey, obj in
  228. self?.itemClick?(itemKey, obj)
  229. }
  230. }
  231. func show(relativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge) {
  232. let contentViewC = (self.contentViewController as? KMEditPDFPopToolBarController)
  233. var width: CGFloat = 392
  234. if self.style.contains(.text) {
  235. if self.style.contains(.image) { // text + image
  236. contentViewC?.itemKeys = [.alignmentLeft, .alignmentCenterX, .alignmentRight, .alignmentjustifiedX, .alignmentTop, .alignmentCenterY, .alignmentBottom, .alignmentjustifiedY]
  237. width = 320
  238. } else { // text
  239. if self.isMultiple {
  240. width = 478
  241. contentViewC?.itemKeys = [.color, .fontStyle, .fontAdd, .fontReduce, .fontBold, .fontItalic, .textAlignment, .separator, .alignmentLeft, .alignmentTop]
  242. } else {
  243. width = 392
  244. contentViewC?.itemKeys = [.color, .fontStyle, .fontAdd, .fontReduce, .fontBold, .fontItalic, .textAlignment]
  245. }
  246. }
  247. } else {
  248. if self.style.contains(.image) { // image
  249. if self.isMultiple {
  250. width = 396
  251. contentViewC?.itemKeys = [.leftRotate, .rightRotate, .separator, .reverseX, .reverseY, .separator, .crop, .replace, .export, .separator, .alignmentLeft, .alignmentTop]
  252. } else {
  253. width = 304
  254. contentViewC?.itemKeys = [.leftRotate, .rightRotate, .separator, .reverseX, .reverseY, .separator, .crop, .replace, .export]
  255. }
  256. } else { // none
  257. }
  258. }
  259. // var position = positioningView.convert(positioningRect.origin, to: nil)
  260. var position = NSEvent.mouseLocation
  261. position.y += 20
  262. position.x -= 60
  263. // self.setFrameOrigin(position)
  264. let frame = NSMakeRect(position.x, position.y, width, 44)
  265. self.setFrame(frame, display: true)
  266. self.contentViewController?.view.frame = NSMakeRect(0, 0, width, 44)
  267. self.orderFront(nil)
  268. // self.makeKeyAndOrderFront(nil)
  269. }
  270. override var isMainWindow: Bool {
  271. return true
  272. }
  273. override var isKeyWindow: Bool {
  274. return true
  275. }
  276. }
  277. class KMEditPDFPopToolBarController: NSViewController {
  278. deinit {
  279. KMPrint("KMEditPDFPopToolBarController deinit.")
  280. }
  281. convenience init() {
  282. self.init(nibName: "KMEditPDFPopToolBarController", bundle: nil)
  283. }
  284. var toolbarView: KMEditPDFToolbarView?
  285. var itemKeys: [KMEditPDFToolbarItemKey] = [] {
  286. didSet {
  287. self.toolbarView?.reloadData()
  288. }
  289. }
  290. var itemClick: ((KMEditPDFToolbarItemKey, Any?)->Void)?
  291. override func viewDidLoad() {
  292. super.viewDidLoad()
  293. // Do view setup here.
  294. self.view.wantsLayer = true
  295. self.view.layer?.backgroundColor = .white
  296. let toolbarView = KMEditPDFToolbarView()
  297. self.toolbarView = toolbarView
  298. toolbarView.frame = self.view.bounds
  299. toolbarView.autoresizingMask = [.width, .height]
  300. self.view.addSubview(toolbarView)
  301. toolbarView.delegate = self
  302. toolbarView.inset = .init(top: 6, left: 4, bottom: 0, right: 0)
  303. toolbarView.reloadData()
  304. }
  305. @objc func _buttonClick(_ sender: NSButton) {
  306. let idx = sender.tag
  307. if idx >= 0 && idx < self.itemKeys.count {
  308. self.itemClick?(self.itemKeys[idx], nil)
  309. }
  310. }
  311. }
  312. extension KMEditPDFPopToolBarController: KMEditPDFToolbarViewDelegate {
  313. func numberOfItems(in toolbarView: KMEditPDFToolbarView) -> Int {
  314. return self.itemKeys.count
  315. }
  316. func toolbarView(_ toolbarView: KMEditPDFToolbarView, viewFor index: Int) -> NSView? {
  317. let itemKey = self.itemKeys[index]
  318. if itemKey == .color {
  319. let colorView = KMEditPDFToolbarItemView()
  320. let view = KMEditPDFColorView()
  321. colorView.view = view
  322. return colorView
  323. } else if itemKey == .fontStyle {
  324. let fontStyleView = KMEditPDFToolbarItemView()
  325. let viewC = KMDesignSelect.init(withType: .Combox)
  326. viewC.isScrollPop = true
  327. fontStyleView.view = viewC.view
  328. fontStyleView.obj = viewC
  329. let familyNames = CPDFFont.familyNames
  330. viewC.removeAllItems()
  331. viewC.addItems(withObjectValues: familyNames)
  332. viewC.selectItem(at: 0)
  333. viewC.delete = self
  334. return fontStyleView
  335. } else if itemKey == .separator {
  336. let colorView = KMEditPDFToolbarItemView()
  337. let view = KMSeparatorLineView()
  338. view.strokeColor = NSColor(hex: "#DADBDE")
  339. colorView.view = view
  340. return colorView
  341. }
  342. let colorView = KMEditPDFToolbarItemView()
  343. let viewC = KMDesignButton(withType: .Image)
  344. colorView.view = viewC.view
  345. colorView.obj = viewC
  346. viewC.pagination()
  347. viewC.tag = index
  348. viewC.target = self
  349. viewC.action = #selector(_buttonClick)
  350. if itemKey == .fontAdd {
  351. viewC.image = NSImage(named: "KMImageNameEditPDFFontAdd")!
  352. } else if itemKey == .fontReduce {
  353. viewC.image = NSImage(named: "KMImageNameEditPDFFontReduce")!
  354. } else if itemKey == .fontBold {
  355. viewC.image = NSImage(named: "KMImageNameEditPDFFontBold")!
  356. } else if itemKey == .fontItalic {
  357. viewC.image = NSImage(named: "KMImageNameEditPDFFontItalic")!
  358. } else if itemKey == .textAlignment {
  359. viewC.image = NSImage(named: "KMImageNameEditPDFAlignCenterSelect")!
  360. }
  361. // 图片
  362. else if itemKey == .leftRotate {
  363. viewC.image = NSImage(named: "KMImageNameEditPDFRotationLeft")!
  364. } else if itemKey == .rightRotate {
  365. viewC.image = NSImage(named: "KMImageNameEditPDFRotationRight")!
  366. } else if itemKey == .reverseX {
  367. viewC.image = NSImage(named: "KMImageNameEditPDFReverseX")!
  368. } else if itemKey == .reverseY {
  369. viewC.image = NSImage(named: "KMImageNameEditPDFReverseY")!
  370. } else if itemKey == .crop {
  371. viewC.image = NSImage(named: "KMImageNameEditPDFCrop")!
  372. } else if itemKey == .replace {
  373. viewC.image = NSImage(named: "KMImageNameEditPDFReplace")!
  374. } else if itemKey == .export {
  375. viewC.image = NSImage(named: "KMImageNameEditPDFExport")!
  376. }
  377. // 对齐
  378. else if itemKey == .alignmentLeft {
  379. viewC.image = NSImage(named: "KMImageNameEditPDFImage45_1")!
  380. } else if itemKey == .alignmentCenterX {
  381. viewC.image = NSImage(named: "KMImageNameEditPDFImage46_1")!
  382. } else if itemKey == .alignmentRight {
  383. viewC.image = NSImage(named: "KMImageNameEditPDFImage47_1")!
  384. } else if itemKey == .alignmentjustifiedX {
  385. viewC.image = NSImage(named: "KMImageNameEditPDFImage21_1")!
  386. } else if itemKey == .alignmentTop {
  387. viewC.image = NSImage(named: "KMImageNameEditPDFImage48_1")!
  388. } else if itemKey == .alignmentCenterY {
  389. viewC.image = NSImage(named: "KMImageNameEditPDFImage49_1")!
  390. } else if itemKey == .alignmentBottom {
  391. viewC.image = NSImage(named: "KMImageNameEditPDFImage50_1")!
  392. } else if itemKey == .alignmentjustifiedY {
  393. viewC.image = NSImage(named: "KMImageNameEditPDFImage20_1")!
  394. }
  395. return colorView
  396. }
  397. func toolbarView(_ toolbarView: KMEditPDFToolbarView, sizeForItemAt index: Int) -> NSSize {
  398. let itemKey = self.itemKeys[index]
  399. if itemKey == .color {
  400. return NSMakeSize(56, 32)
  401. } else if itemKey == .fontStyle {
  402. return NSMakeSize(148, 32)
  403. } else if itemKey == .separator {
  404. return NSMakeSize(16, 32)
  405. }
  406. return NSMakeSize(32, 32)
  407. }
  408. }
  409. extension KMEditPDFPopToolBarController: KMSelectPopButtonDelegate {
  410. func km_comboBoxSelectionDidChange(_ obj: KMDesignSelect) {
  411. // if (self.lineWidthVC == obj) {
  412. // let index = self.lineWidthVC.indexOfSelectedItem
  413. // if index < 0 {
  414. // return
  415. // }
  416. //
  417. // let width = self.lineWidthVC.stringValue.replacingOccurrences(of: "pt", with: "")
  418. // if annotationModel.stampAnnotationType() == .signDot {
  419. // annotationModel.setNoteWidth(CGFloat(width.stringToCGFloat())*5)
  420. // annotationModel.setNoteHeight(CGFloat(width.stringToCGFloat())*5)
  421. // } else {
  422. // annotationModel.setLineWidth(width.stringToCGFloat())
  423. // }
  424. // } else if (self.opacityVC == obj) {
  425. // let index = self.opacityVC.indexOfSelectedItem
  426. // if index < 0 {
  427. // return
  428. // }
  429. //
  430. // let opacity = self.opacityVC.stringValue.replacingOccurrences(of: "%", with: "")
  431. // self.opacitySlider.floatValue = Float(opacity.stringToCGFloat()/100)
  432. // annotationModel.setOpacity(opacity.stringToCGFloat()/100)
  433. // }
  434. //
  435. // refreshUI()
  436. // updateAnnotation()
  437. }
  438. func km_controlTextDidEndEditing(_ obj: KMDesignSelect) {
  439. }
  440. }