8
8
import Foundation
9
9
10
10
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
+ ///
12
17
/// - Parameters:
13
18
/// - rect: The bounding rect of available draw space.
14
19
/// - textSelection: The selection to use.
@@ -25,27 +30,35 @@ extension TextSelectionManager {
25
30
return [ ]
26
31
}
27
32
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
+
28
37
// Calculate the first line and any rects selected
29
38
// If the last line position is not the same as the first, calculate any rects from that line.
30
39
// If there's > 0 space between the first and last positions, add a rect between them to cover any
31
40
// intermediate lines.
32
41
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
+ [ ]
37
47
}
38
48
49
+ fillRects. append ( contentsOf: firstLineRects + lastLineRects)
50
+
39
51
if firstLinePosition. yPos + firstLinePosition. height < lastLinePosition. yPos {
40
52
fillRects. append ( CGRect (
41
- x: rect . minX ,
53
+ x: insetXPos ,
42
54
y: firstLinePosition. yPos + firstLinePosition. height,
43
- width: rect . width ,
55
+ width: insetWidth ,
44
56
height: lastLinePosition. yPos - ( firstLinePosition. yPos + firstLinePosition. height)
45
57
) )
46
58
}
47
59
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 }
49
62
}
50
63
51
64
/// Find fill rects for a specific line position.
0 commit comments