@@ -17,38 +17,95 @@ struct TextLayoutManagerAttachmentsTests {
1717 let layoutManager : TextLayoutManager
1818
1919 init ( ) throws {
20- textView = TextView ( string: " A \n B \n C \n D " )
20+ textView = TextView ( string: " 12 \n 45 \n 78 \n 01 \n " )
2121 textView. frame = NSRect ( x: 0 , y: 0 , width: 1000 , height: 1000 )
2222 textStorage = textView. textStorage
2323 layoutManager = try #require( textView. layoutManager)
2424 }
2525
26+ @Test
27+ func addAndGetAttachments( ) throws {
28+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 8 ) )
29+ #expect( layoutManager. attachments. get ( overlapping: textView. documentRange) . count == 1 )
30+ #expect( layoutManager. attachments. get ( overlapping: NSRange ( start: 0 , end: 3 ) ) . count == 1 )
31+ #expect( layoutManager. attachments. get ( startingIn: NSRange ( start: 0 , end: 3 ) ) . count == 1 )
32+ }
33+
2634 // MARK: - Determine Visible Line Tests
2735
2836 @Test
29- func determineVisibleLinesMovesForwards( ) {
30- layoutManager. attachments. attachments ( overlapping: < #T##NSRange#> )
37+ func determineVisibleLinesMovesForwards( ) throws {
38+ // From middle of the first line, to middle of the third line
39+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 8 ) )
40+
41+ // Start with the first line, should extend to the third line
42+ let originalPosition = try #require( layoutManager. lineStorage. getLine ( atIndex: 0 ) ) // zero-indexed
43+ let newPosition = try #require( layoutManager. determineVisiblePosition ( for: originalPosition) )
44+
45+ #expect( newPosition. indexRange == 0 ... 2 )
46+ #expect( newPosition. position. range == NSRange ( start: 0 , end: 9 ) ) // Lines one -> three
47+ }
48+
49+ @Test
50+ func determineVisibleLinesMovesBackwards( ) throws {
51+ // From middle of the first line, to middle of the third line
52+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 8 ) )
53+
54+ // Start with the third line, should extend back to the first line
55+ let originalPosition = try #require( layoutManager. lineStorage. getLine ( atIndex: 2 ) ) // zero-indexed
56+ let newPosition = try #require( layoutManager. determineVisiblePosition ( for: originalPosition) )
57+
58+ #expect( newPosition. indexRange == 0 ... 2 )
59+ #expect( newPosition. position. range == NSRange ( start: 0 , end: 9 ) ) // Lines one -> three
3160 }
3261
3362 @Test
34- func determineVisibleLinesMovesBackwards( ) {
63+ func determineVisibleLinesMergesMultipleAttachments( ) throws {
64+ // Two attachments, meeting at the third line. `determineVisiblePosition` should merge all four lines.
65+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 7 ) )
66+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 7 , end: 11 ) )
67+
68+ let originalPosition = try #require( layoutManager. lineStorage. getLine ( atIndex: 2 ) ) // zero-indexed
69+ let newPosition = try #require( layoutManager. determineVisiblePosition ( for: originalPosition) )
3570
71+ #expect( newPosition. indexRange == 0 ... 3 )
72+ #expect( newPosition. position. range == NSRange ( start: 0 , end: 12 ) ) // Lines one -> four
3673 }
3774
3875 @Test
39- func determineVisibleLinesMergesMultipleAttachments( ) {
76+ func determineVisibleLinesMergesOverlappingAttachments( ) throws {
77+ // Two attachments, overlapping at the third line. `determineVisiblePosition` should merge all four lines.
78+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 7 ) )
79+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 5 , end: 11 ) )
4080
81+ let originalPosition = try #require( layoutManager. lineStorage. getLine ( atIndex: 2 ) ) // zero-indexed
82+ let newPosition = try #require( layoutManager. determineVisiblePosition ( for: originalPosition) )
83+
84+ #expect( newPosition. indexRange == 0 ... 3 )
85+ #expect( newPosition. position. range == NSRange ( start: 0 , end: 12 ) ) // Lines one -> four
4186 }
4287
4388 // MARK: - Iterator Tests
4489
4590 @Test
4691 func iterateWithAttachments( ) {
92+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 1 , end: 2 ) )
93+
94+ let lines = layoutManager. linesStartingAt ( 0 , until: 1000 )
4795
96+ // Line "5" is from the trailing newline. That shows up as an empty line in the view.
97+ #expect( lines. map { $0. index } == [ 0 , 1 , 2 , 3 , 4 ] )
4898 }
4999
50100 @Test
51101 func iterateWithMultilineAttachments( ) {
102+ // Two attachments, meeting at the third line.
103+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 2 , end: 7 ) )
104+ layoutManager. attachments. add ( DemoTextAttachment ( ) , for: NSRange ( start: 7 , end: 11 ) )
105+
106+ let lines = layoutManager. linesStartingAt ( 0 , until: 1000 )
52107
108+ // Line "5" is from the trailing newline. That shows up as an empty line in the view.
109+ #expect( lines. map { $0. index } == [ 0 , 4 ] )
53110 }
54111}
0 commit comments