work in progress on table indicators

This commit is contained in:
jess 2026-04-06 12:02:09 -07:00
parent de1b494189
commit ee621b7993
1 changed files with 31 additions and 33 deletions

View File

@ -333,7 +333,7 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
private let indicatorRowHeight: CGFloat = 20
private let indicatorColWidth: CGFloat = 30
private var indicatorsVisible = false
private var indicatorsVisible = true
private var indicatorContainer: NSView?
private var focusMonitor: Any?
@ -408,8 +408,8 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
let colCount = table.headers.count
guard colCount > 0 else { return }
let th = totalHeight
let ox = indicatorOffset
let oy = indicatorTopOffset
let ox = indicatorColWidth
let oy = indicatorRowHeight
let gridWidth = columnX(for: colCount) + 1
let fullWidth = gridWidth + ox
let fullHeight = th + oy
@ -467,10 +467,8 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
addSubview(line)
}
if indicatorsVisible {
buildIndicators()
}
}
private func makeCell(text: String, frame: NSRect, isHeader: Bool, row: Int, col: Int) -> NSTextField {
let field = NSTextField(frame: frame)
@ -510,14 +508,6 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
// MARK: - Indicators
private var indicatorOffset: CGFloat {
indicatorsVisible ? indicatorColWidth : 0
}
private var indicatorTopOffset: CGFloat {
indicatorsVisible ? indicatorRowHeight : 0
}
private func buildIndicators() {
indicatorContainer?.removeFromSuperview()
@ -529,10 +519,10 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
let colCount = table.headers.count
let totalRows = 1 + table.rows.count
let th = totalHeight + indicatorTopOffset
let topY = totalHeight + indicatorRowHeight
let indicatorBg = Theme.current.surface0
let corner = NSView(frame: NSRect(x: 0, y: th - indicatorRowHeight, width: indicatorColWidth, height: indicatorRowHeight))
let corner = NSView(frame: NSRect(x: 0, y: topY - indicatorRowHeight, width: indicatorColWidth, height: indicatorRowHeight))
corner.wantsLayer = true
corner.layer?.backgroundColor = indicatorBg.cgColor
container.addSubview(corner)
@ -543,14 +533,14 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
label.font = NSFont.systemFont(ofSize: 10, weight: .medium)
label.textColor = Theme.current.overlay2
label.alignment = .center
label.frame = NSRect(x: x, y: th - indicatorRowHeight, width: columnWidths[col], height: indicatorRowHeight)
label.frame = NSRect(x: x, y: topY - indicatorRowHeight, width: columnWidths[col], height: indicatorRowHeight)
label.wantsLayer = true
label.layer?.backgroundColor = indicatorBg.cgColor
container.addSubview(label)
}
for row in 0..<totalRows {
let y = rowY(for: row)
let y = rowY(for: row) + indicatorRowHeight
let label = NSTextField(labelWithString: "\(row + 1)")
label.font = NSFont.systemFont(ofSize: 10, weight: .medium)
label.textColor = Theme.current.overlay2
@ -565,7 +555,6 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
private func showIndicators() {
guard !indicatorsVisible else { return }
indicatorsVisible = true
buildGrid()
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.2
self.indicatorContainer?.animator().alphaValue = 1
@ -574,14 +563,11 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
private func hideIndicators() {
guard indicatorsVisible else { return }
NSAnimationContext.runAnimationGroup({ ctx in
indicatorsVisible = false
NSAnimationContext.runAnimationGroup { ctx in
ctx.duration = 0.2
self.indicatorContainer?.animator().alphaValue = 0
}, completionHandler: { [weak self] in
guard let self = self else { return }
self.indicatorsVisible = false
self.buildGrid()
})
}
}
private func setupFocusMonitoring() {
@ -597,8 +583,12 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
private func checkFocusState() {
guard let w = window else { return }
let fr = w.firstResponder
let hasFocusedCell = cellFields.joined().contains { field in
fr === field || (fr as? NSTextView)?.delegate === field
var hasFocusedCell = false
if let fieldEditor = fr as? NSTextView,
let editedCell = fieldEditor.delegate as AnyObject? {
hasFocusedCell = cellFields.joined().contains { $0 === editedCell }
} else {
hasFocusedCell = cellFields.joined().contains { $0 === fr }
}
if hasFocusedCell && !indicatorsVisible {
showIndicators()
@ -612,15 +602,14 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
// MARK: - Resize hit detection
private func columnDivider(at point: NSPoint) -> Int? {
let ox = indicatorOffset
let colCount = table.headers.count
for i in 1..<colCount {
let divX = columnX(for: i) - 1 + ox
let divX = columnX(for: i) - 1 + indicatorColWidth
if abs(point.x - divX) <= dividerHitZone {
return i - 1
}
}
let lastX = columnX(for: colCount) + ox
let lastX = columnX(for: colCount) + indicatorColWidth
if abs(point.x - lastX) <= dividerHitZone {
return colCount - 1
}
@ -628,14 +617,13 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
}
private func rowDivider(at point: NSPoint) -> Int? {
let oy = indicatorTopOffset
let totalRows = 1 + table.rows.count
for i in 0..<totalRows {
let divY: CGFloat
if i == 0 {
divY = totalHeight - rowHeights[0] + oy
divY = totalHeight - rowHeights[0] + indicatorRowHeight
} else {
divY = rowY(for: i) + oy
divY = rowY(for: i) + indicatorRowHeight
}
if abs(point.y - divY) <= dividerHitZone {
return i
@ -680,6 +668,10 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
}
override func mouseDown(with event: NSEvent) {
if !indicatorsVisible {
mouseInside = true
showIndicators()
}
let pt = convert(event.locationInWindow, from: nil)
if let col = columnDivider(at: pt) {
if event.clickCount == 2 {
@ -780,6 +772,12 @@ class MarkdownTableView: NSView, NSTextFieldDelegate {
// MARK: - Cell editing
func controlTextDidBeginEditing(_ obj: Notification) {
if !indicatorsVisible {
showIndicators()
}
}
func controlTextDidEndEditing(_ obj: Notification) {
guard let field = obj.object as? NSTextField else { return }
let tag = field.tag