I am trying to produce a custom header for my NSTableView. I would like to change the font of the header text and remove the borders and vertical separators.
My curr
One way to do it, in your NSTableViewDelegate's
viewForTableColumn
-function:
if tableColumn!.identifier == "description" {
let cell = NSTableHeaderCell()
cell.title = "New Title"
cell.backgroundColor = NSColor.redColor()
cell.drawsBackground = true
cell.bordered = false
cell.font = NSFont(name: "Helvetica", size: 16)
tableColumn!.headerCell = cell
}
The above answers works also directly you can use in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableColumns.forEach { (column) in
column.headerCell.backgroundColor = NSColor.white
column.headerCell.drawsBackground = true
column.headerCell.isBordered = false
column.headerCell.attributedStringValue = NSAttributedString(string: column.title, attributes: [NSAttributedString.Key.font: NSFont.systemFont(ofSize: 13)])
}
}
You will need to take over the drawing yourself by subclassing NSTableHeaderCell
, like so:
final class CustomTableHeaderCell : NSTableHeaderCell {
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(textCell: String) {
super.init(textCell: textCell)
self.font = NSFont.boldSystemFontOfSize(20)
}
override func drawWithFrame(cellFrame: NSRect, inView controlView: NSView) {
// skip super.drawWithFrame(), since that is what draws borders
self.drawInteriorWithFrame(cellFrame, inView: controlView)
}
override func drawInteriorWithFrame(cellFrame: NSRect, inView controlView: NSView) {
let titleRect = self.titleRectForBounds(cellFrame)
self.attributedStringValue.drawInRect(titleRect)
}
}
If you are setting up the table programmatically, you would do it like:
let col = NSTableColumn(identifier: id)
col.headerCell = CustomTableHeaderCell(textCell: title)
col.title = title
self.dataTableView.addTableColumn(col)
Otherwise, you should be able to just set the name of your class to your subclass' name in Interface Builder.
Actually both the answers from mprudhom and Pronto contributed nicely to the final fix. Many thanks to both of you.
I thought I'd post my final answer so anyone following on can see how I fixed it.
I couldn't use mprudhom's code alone as my table only had a NSTableHeaderView and no TableHeaderCells. Fortunately Pronto came to the rescue on that:
class MyTable: NSTableView, NSTableViewDataSource, NSTableViewDelegate
{
override func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView?
{
tableColumn!.headerCell = MyTableHeaderCell(textCell: tableColumn!.identifier)
}
}
I used the NSTableHeaderCell code directly from mprudhom:
final class MyTableHeaderCell : NSTableHeaderCell
{
required init?(coder aDecoder: NSCoder)
{
fatalError("init(coder:) has not been implemented")
}
override init(textCell: String)
{
super.init(textCell: textCell)
self.font = NSFont.boldSystemFontOfSize(14)
}
override func drawWithFrame(cellFrame: NSRect, inView controlView: NSView)
{
//super.drawWithFrame(cellFrame, inView: controlView)//, since that is what draws borders
self.drawInteriorWithFrame(cellFrame, inView: controlView)
}
override func drawInteriorWithFrame(cellFrame: NSRect, inView controlView: NSView)
{
let titleRect = self.titleRectForBounds(cellFrame)
self.attributedStringValue.drawInRect(titleRect)
}
}
Once these two methods were implemented, I had one last problem in that the NSTableHeaderView was drawn without the border as required but did have a grey background. So I overrode the NSTableHeaderView class with this method:
class ForecastHeaderView : NSTableHeaderView
{
required init?(coder: NSCoder)
{
super.init(coder: coder)
}
override init(frame frameRect: NSRect)
{
super.init(frame: frameRect)
self.wantsLayer = true
}
override func drawLayer(layer: CALayer, inContext ctx: CGContext)
{
super.drawLayer(layer, inContext: ctx)
layer.backgroundColor = CGColorCreateGenericGray(1.0, 1.0)
}
}