KMPopUpButton.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //
  2. // KMPopUpButton.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2023/10/9.
  6. //
  7. import Cocoa
  8. @objc enum KMPopUpButtonType: Int {
  9. case table = 0
  10. case arrowDown = 1
  11. case arrowUpDown = 2
  12. case noArrow = 3
  13. }
  14. @objcMembers class KMPopUpButton: NSPopUpButton {
  15. var buttonImage: NSImage?
  16. var type: KMPopUpButtonType = .arrowUpDown {
  17. didSet {
  18. switch type {
  19. case .table, .arrowDown, .arrowUpDown:
  20. wantsLayer = true
  21. layer?.borderWidth = 1.0
  22. layer?.cornerRadius = 4.0
  23. layer?.borderColor = KMAppearance.Layout.bgColor().cgColor
  24. bezelStyle = .shadowlessSquare
  25. case .noArrow:
  26. break
  27. }
  28. }
  29. }
  30. override func draw(_ dirtyRect: NSRect) {
  31. super.draw(dirtyRect)
  32. var frameSize = bounds
  33. var image = NSImage(named: KMImageNameUXIconBtnArrowUpdown)
  34. var titleFloat: CGFloat = 8.0
  35. switch type {
  36. case .table:
  37. KMAppearance.Layout.l1Color().setFill()
  38. frameSize.fill()
  39. if let tableImg = self.buttonImage {
  40. var tableRect = NSZeroRect
  41. tableRect.size = tableImg.size
  42. var p1 = frameSize.origin
  43. p1.x += frameSize.size.width - tableImg.size.width - 8
  44. p1.y += (frameSize.size.height - tableImg.size.height) / 2
  45. tableImg.draw(in: NSMakeRect(8, 4, tableImg.size.width, tableImg.size.height),
  46. from: tableRect,
  47. operation: .sourceOver,
  48. fraction: 1.0,
  49. respectFlipped: true,
  50. hints: nil)
  51. titleFloat += tableImg.size.width + 9.0
  52. // 对选中的item设置勾选
  53. for item in super.itemArray {
  54. if item == selectedItem {
  55. item.state = .on
  56. } else {
  57. item.state = .off
  58. }
  59. }
  60. let title = selectedItem?.title as NSString? ?? ""
  61. let titleSize = title.size(withAttributes: [NSAttributedString.Key.font: font as Any])
  62. let titleY = frameSize.origin.y + (frameSize.size.height - titleSize.height) / 2
  63. var rectTitle = frameSize
  64. rectTitle.origin = NSPoint(x: titleFloat, y: titleY)
  65. rectTitle.size.height = titleSize.height
  66. title.draw(in: rectTitle, withAttributes: [NSAttributedString.Key.foregroundColor: KMAppearance.Layout.h0Color()])
  67. }
  68. case .arrowDown:
  69. image = NSImage(named: KMImageNameUXIconBtnArrowDown)
  70. case .arrowUpDown:
  71. break
  72. default:
  73. break
  74. }
  75. var rect = NSRect.zero
  76. rect.size = CGSize(width: 16.0, height: 16.0)
  77. var p = frameSize.origin
  78. p.x += frameSize.size.width - 17
  79. p.y += (frameSize.size.height - 16) / 2
  80. image?.draw(in: NSMakeRect(p.x, p.y, 16.0, 16.0),
  81. from: rect,
  82. operation: .sourceOver,
  83. fraction: 1.0,
  84. respectFlipped: true,
  85. hints: nil)
  86. }
  87. }
  88. class KMPopUpButtonCell: NSPopUpButtonCell {
  89. override func edit(withFrame cellFrame: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, event: NSEvent?) {
  90. super.edit(withFrame: adjustedFrameToVerticallyCenterText(cellFrame), in: controlView, editor: textObj, delegate: delegate, event: event)
  91. }
  92. override func select(withFrame cellFrame: NSRect, in controlView: NSView, editor textObj: NSText, delegate: Any?, start selStart: Int, length selLength: Int) {
  93. super.select(withFrame: adjustedFrameToVerticallyCenterText(cellFrame), in: controlView, editor: textObj, delegate: delegate, start: selStart, length: selLength)
  94. }
  95. override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
  96. super.drawInterior(withFrame: adjustedFrameToVerticallyCenterText(cellFrame), in: controlView)
  97. }
  98. private func adjustedFrameToVerticallyCenterText(_ frame: NSRect) -> NSRect {
  99. let offset = floor((frame.size.height / 2 - (font!.ascender + font!.descender)))
  100. return frame.insetBy(dx: 0.0, dy: offset)
  101. }
  102. }