replace paragraph-spacing positioning hack with compositor block arithmetic

This commit is contained in:
jess 2026-04-07 14:25:15 -07:00
parent 89aa999300
commit 7441ec937c
1 changed files with 18 additions and 52 deletions

View File

@ -1299,62 +1299,54 @@ struct CompositorRepresentable: NSViewRepresentable {
} }
} }
// Collapse source lines and create gaps via paragraph spacing
isUpdatingTables = true isUpdatingTables = true
let tinyFont = NSFont.systemFont(ofSize: 0.1) let tinyFont = NSFont.systemFont(ofSize: 0.1)
let collapsedPara = NSMutableParagraphStyle()
collapsedPara.minimumLineHeight = 0.1
collapsedPara.maximumLineHeight = 0.1
collapsedPara.lineSpacing = 0
collapsedPara.paragraphSpacing = 0
collapsedPara.paragraphSpacingBefore = 0
ts.beginEditing() ts.beginEditing()
for (range, height) in blockSpacings { for (range, height) in blockSpacings {
// Make source text invisible: tiny font, zero foreground alpha
ts.addAttribute(.font, value: tinyFont, range: range) ts.addAttribute(.font, value: tinyFont, range: range)
ts.addAttribute(.foregroundColor, value: NSColor.clear, range: range) ts.addAttribute(.foregroundColor, value: NSColor.clear, range: range)
ts.addAttribute(.paragraphStyle, value: collapsedPara.copy() as! NSParagraphStyle, range: range)
// Collapse line heights and add spacing for the block view
let para = NSMutableParagraphStyle()
para.minimumLineHeight = 0.1
para.maximumLineHeight = 0.1
para.lineSpacing = 0
para.paragraphSpacing = 0
para.paragraphSpacingBefore = 0
ts.addAttribute(.paragraphStyle, value: para, range: range)
// On the last line, add paragraph spacing equal to block height
let lastLineRange = text.lineRange(for: NSRange(location: max(0, NSMaxRange(range) - 1), length: 0)) let lastLineRange = text.lineRange(for: NSRange(location: max(0, NSMaxRange(range) - 1), length: 0))
let lastPara = NSMutableParagraphStyle() let spacerPara = collapsedPara.mutableCopy() as! NSMutableParagraphStyle
lastPara.minimumLineHeight = 0.1 spacerPara.paragraphSpacing = height
lastPara.maximumLineHeight = 0.1 ts.addAttribute(.paragraphStyle, value: spacerPara, range: lastLineRange)
lastPara.lineSpacing = 0
lastPara.paragraphSpacing = height
lastPara.paragraphSpacingBefore = 0
ts.addAttribute(.paragraphStyle, value: lastPara, range: lastLineRange)
} }
ts.endEditing() ts.endEditing()
isUpdatingTables = false isUpdatingTables = false
lm.ensureLayout(for: tc) lm.ensureLayout(for: tc)
// Position blocks at the origin of their collapsed source text // Position blocks using first-glyph origin of collapsed source text
var tableIdx = 0 var tableIdx = 0
var hrIdx = 0 var hrIdx = 0
let x = origin.x + 4
for block in lm.blockRanges { for block in lm.blockRanges {
let glyphRange = lm.glyphRange(forCharacterRange: block.range, actualCharacterRange: nil) let glyphRange = lm.glyphRange(forCharacterRange: block.range, actualCharacterRange: nil)
let rect = lm.boundingRect(forGlyphRange: glyphRange, in: tc) guard glyphRange.length > 0 else { continue }
let x = origin.x + 4 let lineRect = lm.lineFragmentRect(forGlyphAt: glyphRange.location, effectiveRange: nil)
let blockY = lineRect.origin.y + origin.y
switch block.kind { switch block.kind {
case .tableBlock: case .tableBlock:
guard tableIdx < tableBlocks.count else { continue } guard tableIdx < tableBlocks.count else { continue }
let tb = tableBlocks[tableIdx] let tb = tableBlocks[tableIdx]
tableIdx += 1 tableIdx += 1
let tableW = tb.view.frame.width tb.view.frame = NSRect(x: x, y: blockY, width: tb.view.frame.width, height: tb.blockHeight)
tb.view.frame = NSRect(x: x, y: rect.origin.y + origin.y, width: tableW, height: tb.blockHeight)
tv.addSubview(tb.view) tv.addSubview(tb.view)
case .horizontalRule: case .horizontalRule:
guard hrIdx < hrBlocks.count else { continue } guard hrIdx < hrBlocks.count else { continue }
let hb = hrBlocks[hrIdx] let hb = hrBlocks[hrIdx]
hrIdx += 1 hrIdx += 1
let w = tc.containerSize.width - 8 hb.view.frame = NSRect(x: x, y: blockY, width: tc.containerSize.width - 8, height: hb.blockHeight)
hb.view.frame = NSRect(x: x, y: rect.origin.y + origin.y, width: w, height: hb.blockHeight)
tv.addSubview(hb.view) tv.addSubview(hb.view)
default: default:
@ -1373,32 +1365,6 @@ struct CompositorRepresentable: NSViewRepresentable {
ts.beginEditing() ts.beginEditing()
ts.replaceCharacters(in: sourceRange, with: newMarkdown) ts.replaceCharacters(in: sourceRange, with: newMarkdown)
applySyntaxHighlighting(to: ts, format: parent.fileFormat) applySyntaxHighlighting(to: ts, format: parent.fileFormat)
// Collapse new source text and set paragraph spacing for updated table height
let newRange = NSRange(location: sourceRange.location, length: (newMarkdown as NSString).length)
let blockHeight: CGFloat = 28 + CGFloat(table.rows.count) * 26 + 2
let tinyFont = NSFont.systemFont(ofSize: 0.1)
ts.addAttribute(.font, value: tinyFont, range: newRange)
ts.addAttribute(.foregroundColor, value: NSColor.clear, range: newRange)
let collapsePara = NSMutableParagraphStyle()
collapsePara.minimumLineHeight = 0.1
collapsePara.maximumLineHeight = 0.1
collapsePara.lineSpacing = 0
collapsePara.paragraphSpacing = 0
collapsePara.paragraphSpacingBefore = 0
ts.addAttribute(.paragraphStyle, value: collapsePara, range: newRange)
let text = ts.string as NSString
let lastLineRange = text.lineRange(for: NSRange(location: max(0, NSMaxRange(newRange) - 1), length: 0))
let lastPara = NSMutableParagraphStyle()
lastPara.minimumLineHeight = 0.1
lastPara.maximumLineHeight = 0.1
lastPara.lineSpacing = 0
lastPara.paragraphSpacing = blockHeight
lastPara.paragraphSpacingBefore = 0
ts.addAttribute(.paragraphStyle, value: lastPara, range: lastLineRange)
ts.endEditing() ts.endEditing()
(tv as? LineNumberTextView)?.applyEvalSpacing() (tv as? LineNumberTextView)?.applyEvalSpacing()
tv.selectedRanges = sel tv.selectedRanges = sel