KMTextWithIconCell.swift 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. //
  2. // KMTextWithIconCell.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by lizhe on 2024/2/21.
  6. //
  7. import Cocoa
  8. let SKTextWithIconStringKey = "string"
  9. let SKTextWithIconImageKey = "image"
  10. let BORDER_BETWEEN_EDGE_AND_IMAGE: CGFloat = 2.0
  11. let BORDER_BETWEEN_IMAGE_AND_TEXT: CGFloat = 2.0
  12. let IMAGE_OFFSET: CGFloat = 1.0
  13. class KMTextWithIconCell: NSTextFieldCell {
  14. var imageCell: NSImageCell = NSImageCell()
  15. override init(textCell string: String) {
  16. super.init(textCell: string)
  17. commonInit()
  18. }
  19. required init(coder: NSCoder) {
  20. super.init(coder: coder)
  21. commonInit()
  22. }
  23. private func commonInit() {
  24. imageCell.imageScaling = .scaleProportionallyUpOrDown
  25. // if formatter == nil {
  26. // formatter = DictionaryFormatter(key: SKTextWithIconStringKey)
  27. // }
  28. }
  29. override func copy(with zone: NSZone? = nil) -> Any {
  30. let copy = super.copy(with: zone) as! KMTextWithIconCell
  31. copy.imageCell = imageCell.copy() as! NSImageCell
  32. return copy
  33. }
  34. override func cellSize(forBounds rect: NSRect) -> NSSize {
  35. var cellSize = super.cellSize(forBounds: rect)
  36. cellSize.width += cellSize.height - 1 + BORDER_BETWEEN_EDGE_AND_IMAGE + BORDER_BETWEEN_IMAGE_AND_TEXT
  37. cellSize.width = min(cellSize.width, rect.width)
  38. return cellSize
  39. }
  40. private func textRect(forBounds rect: NSRect) -> NSRect {
  41. return KMShrinkRect(rect, NSHeight(rect) - 1 + BORDER_BETWEEN_EDGE_AND_IMAGE + BORDER_BETWEEN_IMAGE_AND_TEXT, .minX)
  42. }
  43. private func iconRect(forBounds rect: NSRect) -> NSRect {
  44. return KMSliceRect(KMShrinkRect(rect, BORDER_BETWEEN_EDGE_AND_IMAGE, .minX), NSHeight(rect) - 1, .minX)
  45. }
  46. override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) {
  47. // let super draw the text
  48. let textRect = textRect(forBounds: cellFrame)
  49. super.drawInterior(withFrame: textRect, in: controlView)
  50. // Draw the image
  51. var imageRect = iconRect(forBounds: cellFrame)
  52. imageRect = KMCenterRectVertically(rect: imageRect, height: NSWidth(imageRect), offset: IMAGE_OFFSET, flipped: controlView.isFlipped)
  53. imageCell.drawInterior(withFrame: imageRect, in: controlView)
  54. }
  55. override func edit(withFrame cellFrame: NSRect, in controlView: NSView, editor textObj: NSText, delegate anObject: Any?, event: NSEvent?) {
  56. super.edit(withFrame: textRect(forBounds: cellFrame), in: controlView, editor: textObj, delegate: anObject, event: event)
  57. }
  58. override func select(withFrame cellFrame: NSRect, in controlView: NSView, editor textObj: NSText, delegate anObject: Any?, start selStart: Int, length selLength: Int) {
  59. super.select(withFrame: textRect(forBounds: cellFrame), in: controlView, editor: textObj, delegate: anObject, start: selStart, length: selLength)
  60. }
  61. override func hitTest(for event: NSEvent, in rect: NSRect, of controlView: NSView) -> NSCell.HitResult {
  62. let textRect = textRect(forBounds: rect)
  63. let mouseLoc = event.location(inPDFListView: controlView)
  64. var hit: NSCell.HitResult = []
  65. if NSMouseInRect(mouseLoc, textRect, controlView.isFlipped) {
  66. hit = super.hitTest(for: event, in: textRect, of: controlView)
  67. } else if NSMouseInRect(mouseLoc, iconRect(forBounds: rect), controlView.isFlipped) {
  68. hit = .contentArea
  69. }
  70. return hit
  71. }
  72. override var objectValue: Any? {
  73. didSet {
  74. if let obj = objectValue as? NSDictionary {
  75. imageCell.image = obj[SKTextWithIconImageKey] as? NSImage
  76. self.stringValue = obj[SKTextWithIconStringKey] as! String
  77. }
  78. }
  79. }
  80. var icon: NSImage? {
  81. return imageCell.image
  82. }
  83. }
  84. extension KMTextWithIconCell {
  85. func KMSliceRect(_ rect: NSRect, _ amount: CGFloat, _ edge: NSRectEdge) -> NSRect {
  86. var rect = rect
  87. var ignored = NSRect.zero
  88. NSDivideRect(rect, &rect, &ignored, amount, edge);
  89. return rect
  90. }
  91. func KMShrinkRect(_ rect: NSRect, _ amount: CGFloat, _ edge: NSRectEdge) -> NSRect {
  92. var rect = rect
  93. var ignored = NSRect.zero
  94. NSDivideRect(rect, &ignored, &rect, amount, edge);
  95. return rect
  96. }
  97. func KMCenterRectVertically(rect: NSRect, height: CGFloat , offset: CGFloat, flipped: Bool) -> NSRect {
  98. var rect = rect
  99. rect.origin.y += 0.5 * (NSHeight(rect) - height);
  100. rect.origin.y = flipped ? ceil(rect.origin.y) - offset : floor(rect.origin.y) + offset;
  101. rect.size.height = height;
  102. return rect;
  103. }
  104. }