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