Skip to content

Commit 41ea36f

Browse files
Inset Selection Rect By Edge Insets (#60)
### Description Insets the drawn selection box by the text view's edge insets. ### Related Issues * #59 ### Checklist <!--- Add things that are not yet implemented above --> - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/user-attachments/assets/74f8a8bd-4467-4b65-b068-96544c230dad
1 parent 76f8364 commit 41ea36f

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

Sources/CodeEditTextView/TextSelectionManager/TextSelectionManager+FillRects.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88
import Foundation
99

1010
extension TextSelectionManager {
11-
/// Calculate a set of rects for a text selection suitable for highlighting the selection.
11+
/// Calculate a set of rects for a text selection suitable for filling with the selection color to indicate a
12+
/// multi-line selection.
13+
///
14+
/// The returned rects are inset by edge insets passed to the text view, the given `rect` parameter can be the 'raw'
15+
/// rect to draw in, no need to inset it before this method call.
16+
///
1217
/// - Parameters:
1318
/// - rect: The bounding rect of available draw space.
1419
/// - textSelection: The selection to use.
@@ -25,27 +30,35 @@ extension TextSelectionManager {
2530
return []
2631
}
2732

33+
let insetXPos = max(layoutManager.edgeInsets.left, rect.minX)
34+
let insetWidth = max(0, rect.maxX - insetXPos - layoutManager.edgeInsets.right)
35+
let insetRect = NSRect(x: insetXPos, y: rect.origin.y, width: insetWidth, height: rect.height)
36+
2837
// Calculate the first line and any rects selected
2938
// If the last line position is not the same as the first, calculate any rects from that line.
3039
// If there's > 0 space between the first and last positions, add a rect between them to cover any
3140
// intermediate lines.
3241

33-
fillRects.append(contentsOf: getFillRects(in: rect, selectionRange: range, forPosition: firstLinePosition))
34-
35-
if lastLinePosition.range != firstLinePosition.range {
36-
fillRects.append(contentsOf: getFillRects(in: rect, selectionRange: range, forPosition: lastLinePosition))
42+
let firstLineRects = getFillRects(in: rect, selectionRange: range, forPosition: firstLinePosition)
43+
let lastLineRects: [CGRect] = if lastLinePosition.range != firstLinePosition.range {
44+
getFillRects(in: rect, selectionRange: range, forPosition: lastLinePosition)
45+
} else {
46+
[]
3747
}
3848

49+
fillRects.append(contentsOf: firstLineRects + lastLineRects)
50+
3951
if firstLinePosition.yPos + firstLinePosition.height < lastLinePosition.yPos {
4052
fillRects.append(CGRect(
41-
x: rect.minX,
53+
x: insetXPos,
4254
y: firstLinePosition.yPos + firstLinePosition.height,
43-
width: rect.width,
55+
width: insetWidth,
4456
height: lastLinePosition.yPos - (firstLinePosition.yPos + firstLinePosition.height)
4557
))
4658
}
4759

48-
return fillRects
60+
// Pixel align these to avoid aliasing on the edges of each rect that should be a solid box.
61+
return fillRects.map { $0.intersection(insetRect).pixelAligned }
4962
}
5063

5164
/// Find fill rects for a specific line position.

0 commit comments

Comments
 (0)