From db2d940b767e6fba1be32c313319a242450d9df8 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Sun, 24 Nov 2024 10:21:08 -0600 Subject: [PATCH 1/3] Inset Selection Rect By Leading Edge --- .../TextSelectionManager/TextSelectionManager+FillRects.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift index 5b3b9a2b5..275352590 100644 --- a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift +++ b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift @@ -38,7 +38,7 @@ extension TextSelectionManager { if firstLinePosition.yPos + firstLinePosition.height < lastLinePosition.yPos { fillRects.append(CGRect( - x: rect.minX, + x: max(layoutManager.edgeInsets.left, rect.minX), y: firstLinePosition.yPos + firstLinePosition.height, width: rect.width, height: lastLinePosition.yPos - (firstLinePosition.yPos + firstLinePosition.height) From 7f51e85218d831c02a62dcb9dda65c7d31460c5a Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Sun, 24 Nov 2024 10:40:24 -0600 Subject: [PATCH 2/3] Handle Right Edge Insets --- .../TextSelectionManager+FillRects.swift | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift index 275352590..7e6a2362e 100644 --- a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift +++ b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift @@ -8,7 +8,11 @@ import Foundation extension TextSelectionManager { - /// Calculate a set of rects for a text selection suitable for highlighting the selection. + /// Calculate a set of rects for a text selection suitable for filling with the selection color to indicate a multi-line selection. + /// + /// The returned rects are inset by edge insets passed to the text view, the given `rect` parameter can be the 'raw' + /// rect to draw in, no need to inset it before this method call. + /// /// - Parameters: /// - rect: The bounding rect of available draw space. /// - textSelection: The selection to use. @@ -25,27 +29,35 @@ extension TextSelectionManager { return [] } + let insetXPos = max(layoutManager.edgeInsets.left, rect.minX) + let insetWidth = max(0, rect.maxX - insetXPos - layoutManager.edgeInsets.right) + let insetRect = NSRect(x: insetXPos, y: rect.origin.y, width: insetWidth, height: rect.height) + // Calculate the first line and any rects selected // If the last line position is not the same as the first, calculate any rects from that line. // If there's > 0 space between the first and last positions, add a rect between them to cover any // intermediate lines. - fillRects.append(contentsOf: getFillRects(in: rect, selectionRange: range, forPosition: firstLinePosition)) - - if lastLinePosition.range != firstLinePosition.range { - fillRects.append(contentsOf: getFillRects(in: rect, selectionRange: range, forPosition: lastLinePosition)) + let firstLineRects = getFillRects(in: rect, selectionRange: range, forPosition: firstLinePosition) + let lastLineRects: [CGRect] = if lastLinePosition.range != firstLinePosition.range { + getFillRects(in: rect, selectionRange: range, forPosition: lastLinePosition) + } else { + [] } + fillRects.append(contentsOf: firstLineRects + lastLineRects) + if firstLinePosition.yPos + firstLinePosition.height < lastLinePosition.yPos { fillRects.append(CGRect( - x: max(layoutManager.edgeInsets.left, rect.minX), + x: insetXPos, y: firstLinePosition.yPos + firstLinePosition.height, - width: rect.width, + width: insetWidth, height: lastLinePosition.yPos - (firstLinePosition.yPos + firstLinePosition.height) )) } - return fillRects + // Pixel align these to avoid aliasing on the edges of each rect that should be a solid box. + return fillRects.map { $0.intersection(insetRect).pixelAligned } } /// Find fill rects for a specific line position. From 6f46b116cc76f15ebe95aec860c3c9df5889fce6 Mon Sep 17 00:00:00 2001 From: Khan Winter <35942988+thecoolwinter@users.noreply.github.com> Date: Thu, 9 Jan 2025 21:13:59 -0600 Subject: [PATCH 3/3] Fix Lint Error --- .../TextSelectionManager/TextSelectionManager+FillRects.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift index 7e6a2362e..46f56758e 100644 --- a/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift +++ b/Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift @@ -8,7 +8,8 @@ import Foundation extension TextSelectionManager { - /// Calculate a set of rects for a text selection suitable for filling with the selection color to indicate a multi-line selection. + /// Calculate a set of rects for a text selection suitable for filling with the selection color to indicate a + /// multi-line selection. /// /// The returned rects are inset by edge insets passed to the text view, the given `rect` parameter can be the 'raw' /// rect to draw in, no need to inset it before this method call.