Last active
November 23, 2024 06:07
-
-
Save Lessica/176c2314336fc861398de1e1045aa368 to your computer and use it in GitHub Desktop.
A Checkbox Cell in NSTableView Column Header
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// CheckboxHeaderCell.swift | |
// | |
// Created by Rachel on 2021/4/26. | |
// Original: https://stackoverflow.com/questions/11961869/checkbox-in-nstableview-column-header | |
// | |
import Cocoa | |
class CheckboxCell: NSButtonCell { | |
var alternateState: NSControl.StateValue = .off { | |
didSet { | |
super.state = alternateState | |
} | |
} | |
// Ignores the default behavior | |
override var state: NSControl.StateValue { | |
get { alternateState } | |
set { } | |
} | |
} | |
class CheckboxHeaderCell: NSTableHeaderCell { | |
private lazy var innerCell: CheckboxCell = { | |
let cell = CheckboxCell() | |
cell.title = "" | |
cell.setButtonType(.switch) | |
cell.type = .nullCellType | |
cell.isBordered = false | |
cell.imagePosition = .imageOnly | |
cell.alignment = .center | |
cell.objectValue = NSNumber(booleanLiteral: false) | |
cell.controlSize = .regular | |
cell.font = NSFont.systemFont(ofSize: NSFont.systemFontSize(for: .small)) | |
cell.allowsMixedState = true | |
return cell | |
}() | |
// Hide the default "Field" text | |
override var textColor: NSColor? { | |
get { .clear } | |
set { } | |
} | |
override var title: String { | |
get { innerCell.title } | |
set { innerCell.title = newValue } | |
} | |
override var image: NSImage? { | |
get { innerCell.image } | |
set { innerCell.image = newValue } | |
} | |
// We should not override `state` of this class. | |
// Instead, a property named `alternateState` is better for accessing its innerCell's state. | |
var alternateState: NSControl.StateValue { | |
get { innerCell.alternateState } | |
set { innerCell.alternateState = newValue } | |
} | |
func toggleAlternateState() -> NSControl.StateValue { | |
innerCell.alternateState = (alternateState != .on ? .on : .off) | |
return innerCell.alternateState | |
} | |
// Override the original -drawWithFrame:inView: will also remove the background or border of the original cell, which is not recommended. | |
override func drawInterior(withFrame cellFrame: NSRect, in controlView: NSView) { | |
super.drawInterior(withFrame: cellFrame, in: controlView) | |
let centeredRect = CGRect( | |
x: cellFrame.midX - innerCell.cellSize.width / 2.0, | |
y: cellFrame.midY - innerCell.cellSize.height / 2.0, | |
width: innerCell.cellSize.width, | |
height: innerCell.cellSize.height | |
) | |
innerCell.draw(withFrame: centeredRect, in: controlView) | |
} | |
} |
This is crashing for me
Copy and pasted the code; have a tableVIew with two columns. XCode 14.2 macOS 12.6.3
Crashes here
override var image: NSImage? {
get { innerCell.image } //<- Crash with Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)
set { innerCell.image = newValue }
}
Any suggestions?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Setup
Send Action
Re-draw