1111#import " SCXcodeMinimapSelectionView.h"
1212
1313#import " IDESourceCodeEditor.h"
14+
1415#import " DVTTextStorage.h"
16+ #import " DVTLayoutManager.h"
17+
1518#import " DVTPointerArray.h"
1619#import " DVTSourceTextView.h"
1720#import " DVTSourceNodeTypes.h"
2528static NSString * const kXcodeSyntaxCommentDocKeywordNodeName = @" xcode.syntax.comment.doc.keyword" ;
2629static NSString * const kXcodeSyntaxPreprocessorNodeName = @" xcode.syntax.preprocessor" ;
2730
31+ static NSString * const IDEEditorDocumentDidChangeNotification = @" IDEEditorDocumentDidChangeNotification" ;
32+ static NSString * const IDESourceCodeEditorTextViewBoundsDidChangeNotification = @" IDESourceCodeEditorTextViewBoundsDidChangeNotification" ;
2833static NSString * const DVTFontAndColorSourceTextSettingsChangedNotification = @" DVTFontAndColorSourceTextSettingsChangedNotification" ;
2934
35+
36+ @interface NSObject (SCXcodeMinimapDelayedLayoutManager)
37+
38+ - (void )sc_performBlock : (void (^)(void ))block afterDelay : (NSTimeInterval )delay cancelPreviousRequest : (BOOL )cancel ;
39+
40+ @end
41+
42+
43+ @interface SCXcodeMinimapDelayedLayoutManager : DVTLayoutManager
44+
45+ @property (nonatomic , strong ) NSValue *combinedRangeValue;
46+
47+ @end
48+
49+
3050@interface SCXcodeMinimapView () <NSLayoutManagerDelegate >
3151
52+ @property (nonatomic , strong ) IDESourceCodeEditor *editor;
3253@property (nonatomic , strong ) NSScrollView *editorScrollView;
3354@property (nonatomic , strong ) DVTSourceTextView *editorTextView;
3455
3556@property (nonatomic , strong ) NSScrollView *scrollView;
3657@property (nonatomic , strong ) DVTSourceTextView *textView;
3758@property (nonatomic , strong ) SCXcodeMinimapSelectionView *selectionView;
59+ @property (nonatomic , strong ) IDESourceCodeDocument *document;
3860
3961@end
4062
@@ -49,12 +71,15 @@ - (instancetype)initWithFrame:(NSRect)frame editor:(IDESourceCodeEditor *)editor
4971{
5072 if (self = [super initWithFrame: frame])
5173 {
74+ self.editor = editor;
5275 self.editorScrollView = editor.scrollView ;
5376 self.editorTextView = editor.textView ;
5477
78+
5579 [self setWantsLayer: YES ];
5680 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
5781
82+
5883 self.scrollView = [[NSScrollView alloc ] initWithFrame: self .bounds];
5984 [self .scrollView setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
6085 [self .scrollView setDrawsBackground: NO ];
@@ -64,32 +89,45 @@ - (instancetype)initWithFrame:(NSRect)frame editor:(IDESourceCodeEditor *)editor
6489 [self addSubview: self .scrollView];
6590
6691 self.textView = [[DVTSourceTextView alloc ] initWithFrame: self .editorTextView.bounds];
67- [self .textView setTextStorage: editor.textView.textStorage];
92+ SCXcodeMinimapDelayedLayoutManager *layoutManager = [[SCXcodeMinimapDelayedLayoutManager alloc ] init ];
93+ [self .textView.textContainer replaceLayoutManager: layoutManager];
6894 [self .textView setEditable: NO ];
6995 [self .textView setSelectable: NO ];
7096
97+ [self .editorTextView.textStorage addLayoutManager: layoutManager];
98+
7199 [self .scrollView setDocumentView: self .textView];
72100
101+ [self .scrollView setAllowsMagnification: YES ];
102+ [self .scrollView setMinMagnification: kDefaultZoomLevel ];
103+ [self .scrollView setMagnification: kDefaultZoomLevel ];
104+
105+
73106 self.selectionView = [[SCXcodeMinimapSelectionView alloc ] init ];
74107 [self .textView addSubview: _selectionView];
75108
109+
76110 [self updateTheme ];
77111
112+
113+ __weak typeof (self) weakSelf = self;
78114 [[NSNotificationCenter defaultCenter ] addObserverForName: SCXodeMinimapShowNotification object: nil queue: nil usingBlock: ^(NSNotification *note) {
79- [self setVisible: YES ];
115+ [weakSelf setVisible: YES ];
80116 }];
81117
82118 [[NSNotificationCenter defaultCenter ] addObserverForName: SCXodeMinimapHideNotification object: nil queue: nil usingBlock: ^(NSNotification *note) {
83- [self setVisible: NO ];
119+ [weakSelf setVisible: NO ];
84120 }];
85121
86122 [[NSNotificationCenter defaultCenter ] addObserverForName: DVTFontAndColorSourceTextSettingsChangedNotification object: nil queue: nil usingBlock: ^(NSNotification *note) {
87- [self updateTheme ];
123+ [weakSelf updateTheme ];
88124 }];
89125
90- [self .scrollView setAllowsMagnification: YES ];
91- [self .scrollView setMinMagnification: kDefaultZoomLevel ];
92- [self .scrollView setMagnification: kDefaultZoomLevel ];
126+ [[NSNotificationCenter defaultCenter ] addObserverForName: IDESourceCodeEditorTextViewBoundsDidChangeNotification object: nil queue: nil usingBlock: ^(NSNotification *note) {
127+ if ([note.object isEqual: weakSelf.editor]) {
128+ [self updateOffset ];
129+ }
130+ }];
93131 }
94132
95133 return self;
@@ -111,12 +149,17 @@ - (void)setVisible:(BOOL)visible
111149
112150 // Ensure the layout manager's delegate is set to self. The DVTSourceTextView resets it if called to early.
113151 [self .textView.layoutManager setDelegate: self ];
152+ [self .textView.layoutManager setAllowsNonContiguousLayout: NO ];
114153}
115154
116155#pragma mark - NSLayoutManagerDelegate
117156
118157- (NSDictionary *)layoutManager : (NSLayoutManager *)layoutManager shouldUseTemporaryAttributes : (NSDictionary *)attrs forDrawingToScreen : (BOOL )toScreen atCharacterIndex : (NSUInteger )charIndex effectiveRange : (NSRangePointer )effectiveCharRange
119158{
159+ if (!toScreen || self.hidden ) {
160+ return nil ;
161+ }
162+
120163 DVTTextStorage *storage = [self .editorTextView textStorage ];
121164
122165 short currentNodeId = [storage nodeTypeAtCharacterIndex: charIndex effectiveRange: effectiveCharRange context: nil ];
@@ -151,7 +194,6 @@ - (void)layoutManager:(NSLayoutManager *)layoutManager didCompleteLayoutForTextC
151194 }
152195}
153196
154-
155197#pragma mark - Navigation
156198
157199- (void )updateOffset
@@ -165,7 +207,6 @@ - (void)updateOffset
165207 NSRect selectionViewFrame = NSMakeRect (0 , 0 , self.bounds .size .width * (1 / self.scrollView .magnification ), self.editorScrollView .visibleRect .size .height );
166208
167209 if (editorContentHeight == 0 .0f ) {
168- NSLog (@" editorContentHeight IS %f " , editorContentHeight);
169210 [self .selectionView setFrame: selectionViewFrame];
170211 return ;
171212 }
@@ -234,3 +275,75 @@ - (void)resizeWithOldSuperviewSize:(NSSize)oldSize
234275}
235276
236277@end
278+
279+
280+ @implementation SCXcodeMinimapDelayedLayoutManager
281+
282+ - (void )delayedAddOperation : (NSOperation *)operation {
283+ [[NSOperationQueue currentQueue ] addOperation: operation];
284+ }
285+
286+ - (void )performBlock : (void (^)(void ))block afterDelay : (NSTimeInterval )delay {
287+ [self performSelector: @selector (delayedAddOperation: )
288+ withObject: [NSBlockOperation blockOperationWithBlock: block]
289+ afterDelay: delay];
290+ }
291+
292+ - (void )performBlock : (void (^)(void ))block afterDelay : (NSTimeInterval )delay cancelPreviousRequest : (BOOL )cancel {
293+ if (cancel) {
294+ [NSObject cancelPreviousPerformRequestsWithTarget: self ];
295+ }
296+ [self performBlock: block afterDelay: delay];
297+ }
298+
299+ - (void )invalidateDisplayForCharacterRange : (NSRange )charRange
300+ {
301+ if (self.combinedRangeValue ) {
302+ self.combinedRangeValue = [NSValue valueWithRange: NSUnionRange (self .combinedRangeValue.rangeValue, charRange)];
303+ } else {
304+ self.combinedRangeValue = [NSValue valueWithRange: charRange];
305+ }
306+
307+ [self performBlock: ^{
308+
309+ NSRange range = NSIntersectionRange (self.combinedRangeValue .rangeValue , NSMakeRange (0 , self.textStorage .length ));
310+ [super invalidateDisplayForCharacterRange: range];
311+ self.combinedRangeValue = nil ;
312+ } afterDelay: 0 .5f cancelPreviousRequest: YES ];
313+ }
314+
315+ - (void )_invalidateLayoutForExtendedCharacterRange : (NSRange )charRange isSoft : (BOOL )isSoft
316+ {
317+ if (isSoft) {
318+ [super _invalidateLayoutForExtendedCharacterRange: charRange isSoft: isSoft];
319+ }
320+ }
321+
322+ - (void )textStorage : (id )arg1 edited : (unsigned long long )arg2 range : (struct _NSRange)arg3 changeInLength : (long long )arg4 invalidatedRange : (struct _NSRange)arg5
323+ {
324+
325+ }
326+
327+ @end
328+
329+
330+ @implementation NSObject (SCXcodeMinimapDelayedLayoutManager)
331+
332+ - (void )sc_performBlock : (void (^)(void ))block afterDelay : (NSTimeInterval )delay {
333+ [self performSelector: @selector (delayedAddOperation: )
334+ withObject: [NSBlockOperation blockOperationWithBlock: block]
335+ afterDelay: delay];
336+ }
337+
338+ - (void )sc_performBlock : (void (^)(void ))block afterDelay : (NSTimeInterval )delay cancelPreviousRequest : (BOOL )cancel {
339+ if (cancel) {
340+ [NSObject cancelPreviousPerformRequestsWithTarget: self ];
341+ }
342+ [self sc_performBlock: block afterDelay: delay];
343+ }
344+
345+ - (void )sc_delayedAddOperation : (NSOperation *)operation {
346+ [[NSOperationQueue currentQueue ] addOperation: operation];
347+ }
348+
349+ @end
0 commit comments