@@ -11,17 +11,40 @@ import CodeEditTextView
1111class MinimapView : NSView {
1212 weak var textView : TextView ?
1313
14+ /// The container scrollview for the minimap contents.
1415 let scrollView : NSScrollView
15- let contentView : FlippedNSView
16+ /// The view text lines are rendered into.
17+ let contentView : MinimapContentView
18+ /// The box displaying the visible region on the minimap.
19+ let documentVisibleView : NSView
20+
21+ /// The layout manager that uses the ``lineRenderer`` to render and layout lines.
1622 var layoutManager : TextLayoutManager ?
23+ /// A custom line renderer that lays out lines of text as 2px tall and draws contents as small lines
24+ /// using ``MinimapLineFragmentView``
1725 let lineRenderer : MinimapLineRenderer
1826
1927 var theme : EditorTheme {
2028 didSet {
29+ documentVisibleView. layer? . backgroundColor = theme. text. color. withAlphaComponent ( 0.1 ) . cgColor
2130 layer? . backgroundColor = theme. background. cgColor
2231 }
2332 }
2433
34+ var visibleTextRange : NSRange ? {
35+ guard let layoutManager = layoutManager else { return nil }
36+ let minY = max ( visibleRect. minY, 0 )
37+ let maxY = min ( visibleRect. maxY, layoutManager. estimatedHeight ( ) )
38+ guard let minYLine = layoutManager. textLineForPosition ( minY) ,
39+ let maxYLine = layoutManager. textLineForPosition ( maxY) else {
40+ return nil
41+ }
42+ return NSRange (
43+ location: minYLine. range. location,
44+ length: ( maxYLine. range. location - minYLine. range. location) + maxYLine. range. length
45+ )
46+ }
47+
2548 init ( textView: TextView , theme: EditorTheme ) {
2649 self . textView = textView
2750 self . theme = theme
@@ -34,12 +57,18 @@ class MinimapView: NSView {
3457 scrollView. drawsBackground = false
3558 scrollView. verticalScrollElasticity = . none
3659
37- self . contentView = FlippedNSView ( frame: . zero)
60+ self . contentView = MinimapContentView ( frame: . zero)
3861 contentView. translatesAutoresizingMaskIntoConstraints = false
3962
63+ self . documentVisibleView = NSView ( )
64+ documentVisibleView. translatesAutoresizingMaskIntoConstraints = false
65+ documentVisibleView. wantsLayer = true
66+ documentVisibleView. layer? . backgroundColor = theme. text. color. withAlphaComponent ( 0.1 ) . cgColor
67+
4068 super. init ( frame: . zero)
4169
4270 addSubview ( scrollView)
71+ addSubview ( documentVisibleView)
4372 scrollView. documentView = contentView
4473
4574 self . translatesAutoresizingMaskIntoConstraints = false
@@ -58,6 +87,7 @@ class MinimapView: NSView {
5887 layer? . backgroundColor = theme. background. cgColor
5988
6089 setUpConstraints ( )
90+ setUpListeners ( )
6191 }
6292
6393 private func setUpConstraints( ) {
@@ -67,10 +97,40 @@ class MinimapView: NSView {
6797 scrollView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
6898 scrollView. trailingAnchor. constraint ( equalTo: trailingAnchor) ,
6999
70- contentView. widthAnchor. constraint ( equalTo: widthAnchor)
100+ contentView. widthAnchor. constraint ( equalTo: widthAnchor) ,
101+
102+ documentVisibleView. leadingAnchor. constraint ( equalTo: leadingAnchor) ,
103+ documentVisibleView. trailingAnchor. constraint ( equalTo: trailingAnchor)
71104 ] )
72105 }
73106
107+ private func setUpListeners( ) {
108+ guard let editorScrollView = textView? . enclosingScrollView else { return }
109+ // Need to listen to:
110+ // - ScrollView offset changed
111+ // - ScrollView frame changed
112+ // and update the document visible box to match.
113+ NotificationCenter . default. addObserver (
114+ forName: NSView . boundsDidChangeNotification,
115+ object: editorScrollView. contentView,
116+ queue: . main
117+ ) { [ weak self] _ in
118+ // Scroll changed
119+ self ? . layoutManager? . layoutLines ( )
120+ self ? . updateDocumentVisibleViewPosition ( )
121+ }
122+
123+ NotificationCenter . default. addObserver (
124+ forName: NSView . frameDidChangeNotification,
125+ object: editorScrollView. contentView,
126+ queue: . main
127+ ) { [ weak self] _ in
128+ // Frame changed
129+ self ? . layoutManager? . layoutLines ( )
130+ self ? . updateDocumentVisibleViewPosition ( )
131+ }
132+ }
133+
74134 required init ? ( coder: NSCoder ) {
75135 fatalError ( " init(coder:) has not been implemented " )
76136 }
@@ -86,18 +146,6 @@ class MinimapView: NSView {
86146 super. layout ( )
87147 }
88148
89- override func draw( _ dirtyRect: NSRect ) {
90- guard let context = NSGraphicsContext . current? . cgContext else { return }
91- context. saveGState ( )
92-
93- context. setFillColor ( NSColor . separatorColor. cgColor)
94- context. fill ( [
95- CGRect ( x: 0 , y: 0 , width: 1 , height: frame. height)
96- ] )
97-
98- context. restoreGState ( )
99- }
100-
101149 override func hitTest( _ point: NSPoint ) -> NSView ? {
102150 if visibleRect. contains ( point) {
103151 return self
0 commit comments