From 5c0e0fe1d5e0217af411472e2a90daa9d73d106f Mon Sep 17 00:00:00 2001 From: Marcin Krzyzanowski Date: Thu, 2 Jan 2025 02:19:20 +0100 Subject: [PATCH] Improve gutter line number cell layout and marker positioning - Store text size in `STGutterLineNumberCell` for more efficient layout - Add `firstBaselineOffsetFromTop` to `STGutterLineNumberCell` for proper vertical alignment - Position gutter markers based on the text size and baseline of the corresponding line number cell - Ensure marker views don't exceed the height of the line number cell --- .../Gutter/STGutterLineNumberCell.swift | 12 ++++++++---- Sources/STTextViewAppKit/Gutter/STGutterView.swift | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/STTextViewAppKit/Gutter/STGutterLineNumberCell.swift b/Sources/STTextViewAppKit/Gutter/STGutterLineNumberCell.swift index 9424943..610400e 100644 --- a/Sources/STTextViewAppKit/Gutter/STGutterLineNumberCell.swift +++ b/Sources/STTextViewAppKit/Gutter/STGutterLineNumberCell.swift @@ -9,7 +9,7 @@ final class STGutterLineNumberCell: NSView { let lineNumber: Int private let firstBaseline: CGFloat private let ctLine: CTLine - private let textWidth: CGFloat + let textSize: CGSize var insets: STRulerInsets = STRulerInsets() override func animation(forKey key: NSAnimatablePropertyKey) -> Any? { @@ -20,13 +20,17 @@ final class STGutterLineNumberCell: NSView { "\(super.debugDescription) (number: \(lineNumber))" } + override var firstBaselineOffsetFromTop: CGFloat { + firstBaseline + } + init(firstBaseline: CGFloat, attributes: [NSAttributedString.Key: Any], number: Int) { self.lineNumber = number self.firstBaseline = firstBaseline let attributedString = NSAttributedString(string: "\(number)", attributes: attributes) self.ctLine = CTLineCreateWithAttributedString(attributedString) - self.textWidth = ceil(CTLineGetTypographicBounds(ctLine, nil, nil, nil)) + self.textSize = CGSize(width: ceil(CTLineGetTypographicBounds(ctLine, nil, nil, nil)), height: ctLine.height()) super.init(frame: .zero) wantsLayer = true @@ -49,7 +53,7 @@ final class STGutterLineNumberCell: NSView { } override var intrinsicContentSize: NSSize { - NSSize(width: textWidth + insets.trailing + insets.leading, height: 14) + NSSize(width: textSize.width + insets.trailing + insets.leading, height: textSize.height) } override func draw(_ rect: CGRect) { @@ -63,7 +67,7 @@ final class STGutterLineNumberCell: NSView { ctx.textMatrix = CGAffineTransform(scaleX: 1, y: isFlipped ? -1 : 1) // align to right - ctx.textPosition = CGPoint(x: frame.width - (textWidth + insets.trailing), y: firstBaseline) + ctx.textPosition = CGPoint(x: frame.width - (textSize.width + insets.trailing), y: firstBaseline) CTLineDraw(ctLine, ctx) ctx.restoreGState() } diff --git a/Sources/STTextViewAppKit/Gutter/STGutterView.swift b/Sources/STTextViewAppKit/Gutter/STGutterView.swift index 00f2c35..896a652 100644 --- a/Sources/STTextViewAppKit/Gutter/STGutterView.swift +++ b/Sources/STTextViewAppKit/Gutter/STGutterView.swift @@ -164,9 +164,10 @@ open class STGutterView: NSView, NSDraggingSource { } if let cellView { - markerContainerView.addSubview(marker.view) - marker.view.frame.size = cellView.frame.size marker.view.frame.origin = cellView.frame.origin + marker.view.frame.size = cellView.frame.size + marker.view.frame.size.height = min(cellView.textSize.height + cellView.firstBaselineOffsetFromTop, cellView.frame.size.height) + markerContainerView.addSubview(marker.view) } } }