Skip to content

Commit aca2da4

Browse files
committed
fix(datagrid): size the two-line header from font metrics so title and comment never overlap
The captured single-line height could come back smaller than the title glyphs, collapsing the name band into the comment line. Drive the header height and the name band from fixed font-derived metrics instead. Claude-Session: https://claude.ai/code/session_0198faM6VCrViRU4XwRoS1DC
1 parent 951baeb commit aca2da4

3 files changed

Lines changed: 10 additions & 10 deletions

File tree

TablePro/Views/Results/SortableHeaderCell.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ final class SortableHeaderCell: NSTableHeaderCell {
2323
private static let funnelSize = NSSize(width: 13, height: 13)
2424
private static let funnelPointSize: CGFloat = 11
2525
private static let subtitleFont = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize - 1)
26+
private static let titleMetricFont = NSFont.systemFont(ofSize: NSFont.smallSystemFontSize)
27+
static let titleBandHeight: CGFloat = ceil(SortableHeaderCell.titleMetricFont.boundingRectForFont.height) + 6
2628
static let commentBandHeight: CGFloat = ceil(SortableHeaderCell.subtitleFont.boundingRectForFont.height) + 4
29+
static let twoLineHeaderHeight: CGFloat = SortableHeaderCell.titleBandHeight + SortableHeaderCell.commentBandHeight
2730

2831
override init(textCell string: String) {
2932
super.init(textCell: string)
@@ -107,7 +110,7 @@ final class SortableHeaderCell: NSTableHeaderCell {
107110

108111
func nameBandRect(forBounds rect: NSRect) -> NSRect {
109112
guard isTwoLineLayout else { return rect }
110-
let bandHeight = max(0, rect.height - Self.commentBandHeight)
113+
let bandHeight = min(rect.height, Self.titleBandHeight)
111114
return NSRect(x: rect.minX, y: rect.minY, width: rect.width, height: bandHeight)
112115
}
113116

TablePro/Views/Results/SortableHeaderView.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ final class SortableHeaderView: NSTableHeaderView {
7070
private var dragOccurredDuringClick = false
7171
private var mouseMovedTrackingArea: NSTrackingArea?
7272
private var hoveredColumnIndex: Int?
73-
private var baseHeight: CGFloat = 0
7473

7574
var showsCommentLine: Bool = false {
7675
didSet {
@@ -82,20 +81,17 @@ final class SortableHeaderView: NSTableHeaderView {
8281

8382
override init(frame frameRect: NSRect) {
8483
super.init(frame: frameRect)
85-
baseHeight = frameRect.height
8684
}
8785

8886
required init?(coder: NSCoder) {
8987
super.init(coder: coder)
90-
baseHeight = frame.height
9188
}
9289

9390
override func setFrameSize(_ newSize: NSSize) {
94-
if baseHeight <= 0 {
95-
baseHeight = newSize.height
96-
}
9791
var size = newSize
98-
size.height = showsCommentLine ? baseHeight + SortableHeaderCell.commentBandHeight : baseHeight
92+
if showsCommentLine {
93+
size.height = max(newSize.height, SortableHeaderCell.twoLineHeaderHeight)
94+
}
9995
super.setFrameSize(size)
10096
}
10197

TableProTests/Views/Results/SortableHeaderCellTests.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,14 @@ struct SortableHeaderCellTests {
7070
func twoLineLayoutReservesCommentBandBelowName() {
7171
let cell = SortableHeaderCell(textCell: "id")
7272
cell.isTwoLineLayout = true
73-
let bounds = NSRect(x: 0, y: 0, width: 100, height: 38)
73+
let bounds = NSRect(x: 0, y: 0, width: 100, height: SortableHeaderCell.twoLineHeaderHeight)
7474

7575
let nameBand = cell.nameBandRect(forBounds: bounds)
7676

7777
#expect(nameBand.minY == bounds.minY)
78-
#expect(nameBand.height == bounds.height - SortableHeaderCell.commentBandHeight)
78+
#expect(nameBand.height == SortableHeaderCell.titleBandHeight)
7979
#expect(nameBand.maxY < bounds.maxY)
80+
#expect(bounds.maxY - nameBand.maxY == SortableHeaderCell.commentBandHeight)
8081
}
8182

8283
@Test("Funnel aligns to the name band in a two-line header")

0 commit comments

Comments
 (0)