| Line 31... |
Line 31... |
| 31 |
* Created by Hans-J. Bibiko on 15/02/2011.
|
31 |
* Created by Hans-J. Bibiko on 15/02/2011.
|
| 32 |
*
|
32 |
*
|
| 33 |
*/
|
33 |
*/
|
| 34 |
|
34 |
|
| 35 |
#import "RScriptEditorTextView.h"
|
35 |
#import "RScriptEditorTextView.h"
|
| - |
|
36 |
#import "RScriptEditorTextStorage.h"
|
| - |
|
37 |
#import "RScriptEditorTypesetter.h"
|
| - |
|
38 |
#import "RScriptEditorLayoutManager.h"
|
| - |
|
39 |
#import "FoldingSignTextAttachmentCell.h"
|
| 36 |
#import "RGUI.h"
|
40 |
#import "RGUI.h"
|
| 37 |
|
41 |
|
| 38 |
|
42 |
|
| 39 |
#pragma mark -
|
43 |
#pragma mark -
|
| 40 |
#pragma mark flex init
|
44 |
#pragma mark flex init
|
| Line 110... |
Line 114... |
| 110 |
|
114 |
|
| 111 |
@implementation RScriptEditorTextView
|
115 |
@implementation RScriptEditorTextView
|
| 112 |
|
116 |
|
| 113 |
- (void)awakeFromNib
|
117 |
- (void)awakeFromNib
|
| 114 |
{
|
118 |
{
|
| - |
|
119 |
|
| 115 |
// we are a subclass of RTextView which has its own awake and we must call it
|
120 |
// we are a subclass of RTextView which has its own awake and we must call it
|
| 116 |
[super awakeFromNib];
|
121 |
[super awakeFromNib];
|
| - |
|
122 |
|
| 117 |
SLog(@"RScriptEditorTextView: awakeFromNib <%@>", self);
|
123 |
SLog(@"RScriptEditorTextView: awakeFromNib <%@>", self);
|
| 118 |
isSyntaxHighlighting = NO;
|
- |
|
| - |
|
124 |
|
| 119 |
prefs = [[NSUserDefaults standardUserDefaults] retain];
|
125 |
prefs = [[NSUserDefaults standardUserDefaults] retain];
|
| 120 |
[[Preferences sharedPreferences] addDependent:self];
|
126 |
[[Preferences sharedPreferences] addDependent:self];
|
| 121 |
|
127 |
|
| - |
|
128 |
lineNumberingEnabled = [Preferences flagForKey:showLineNumbersKey withDefault:NO];
|
| - |
|
129 |
|
| - |
|
130 |
// <TODO> enable for folding
|
| - |
|
131 |
// theTextStorage = [[RScriptEditorTextStorage alloc] init];
|
| - |
|
132 |
theTextStorage = [self textStorage];
|
| - |
|
133 |
|
| - |
|
134 |
// Set self as delegate for the textView's textStorage to enable syntax highlighting,
|
| - |
|
135 |
[theTextStorage setDelegate:self];
|
| - |
|
136 |
|
| - |
|
137 |
// <TODO> enable for folding
|
| - |
|
138 |
// Make sure using foldingLayoutManager
|
| - |
|
139 |
// if (![[self layoutManager] isKindOfClass:[RScriptEditorLayoutManager class]]) {
|
| - |
|
140 |
// RScriptEditorLayoutManager *layoutManager = [[RScriptEditorLayoutManager alloc] init];
|
| - |
|
141 |
// [[self textContainer] replaceLayoutManager:layoutManager];
|
| - |
|
142 |
// [layoutManager release];
|
| - |
|
143 |
// }
|
| - |
|
144 |
|
| - |
|
145 |
// disabled to get the current text range in textView safer
|
| - |
|
146 |
[[self layoutManager] setBackgroundLayoutEnabled:NO];
|
| - |
|
147 |
[[self layoutManager] replaceTextStorage:theTextStorage];
|
| - |
|
148 |
|
| - |
|
149 |
if(lineNumberingEnabled) {
|
| - |
|
150 |
|
| - |
|
151 |
SLog(@"RScriptEditorTextView: set up line numbering <%@>", self);
|
| - |
|
152 |
|
| - |
|
153 |
NoodleLineNumberView *theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
|
| - |
|
154 |
[scrollView setVerticalRulerView:theRulerView];
|
| - |
|
155 |
[scrollView setHasHorizontalRuler:NO];
|
| - |
|
156 |
[scrollView setHasVerticalRuler:YES];
|
| - |
|
157 |
[scrollView setRulersVisible:YES];
|
| - |
|
158 |
[theRulerView release];
|
| - |
|
159 |
[self display];
|
| - |
|
160 |
}
|
| - |
|
161 |
|
| - |
|
162 |
|
| - |
|
163 |
isSyntaxHighlighting = NO;
|
| - |
|
164 |
|
| 122 |
if([prefs objectForKey:highlightCurrentLine] == nil) [prefs setBool:YES forKey:highlightCurrentLine];
|
165 |
if([prefs objectForKey:highlightCurrentLine] == nil) [prefs setBool:YES forKey:highlightCurrentLine];
|
| 123 |
if([prefs objectForKey:indentNewLines] == nil) [prefs setBool:YES forKey:indentNewLines];
|
166 |
if([prefs objectForKey:indentNewLines] == nil) [prefs setBool:YES forKey:indentNewLines];
|
| 124 |
|
167 |
|
| 125 |
[self setFont:[Preferences unarchivedObjectForKey:RScriptEditorDefaultFont withDefault:[NSFont fontWithName:@"Monaco" size:11]]];
|
168 |
[self setFont:[Preferences unarchivedObjectForKey:RScriptEditorDefaultFont withDefault:[NSFont fontWithName:@"Monaco" size:11]]];
|
| 126 |
|
169 |
|
| 127 |
// Set self as delegate for the textView's textStorage to enable syntax highlighting,
|
- |
|
| 128 |
[[self textStorage] setDelegate:self];
|
- |
|
| 129 |
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
- |
|
| 130 |
[[self layoutManager] setAllowsNonContiguousLayout:YES];
|
- |
|
| 131 |
#endif
|
- |
|
| 132 |
|
- |
|
| 133 |
// Set defaults for general usage
|
170 |
// Set defaults for general usage
|
| 134 |
braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
|
171 |
braceHighlightInterval = [Preferences floatForKey:HighlightIntervalKey withDefault:0.3f];
|
| 135 |
lineNumberingEnabled = [Preferences flagForKey:showLineNumbersKey withDefault:NO];
|
- |
|
| 136 |
argsHints = [Preferences flagForKey:prefShowArgsHints withDefault:YES];
|
172 |
argsHints = [Preferences flagForKey:prefShowArgsHints withDefault:YES];
|
| 137 |
lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault:YES];
|
173 |
lineWrappingEnabled = [Preferences flagForKey:enableLineWrappingKey withDefault:YES];
|
| 138 |
syntaxHighlightingEnabled = [Preferences flagForKey:showSyntaxColoringKey withDefault:YES];
|
174 |
syntaxHighlightingEnabled = [Preferences flagForKey:showSyntaxColoringKey withDefault:YES];
|
| 139 |
|
175 |
|
| 140 |
deleteBackward = NO;
|
176 |
deleteBackward = NO;
|
| Line 147... |
Line 183... |
| 147 |
if([[self delegate] isRdDocument])
|
183 |
if([[self delegate] isRdDocument])
|
| 148 |
editorToolbar = [[RdEditorToolbar alloc] initWithEditor:[self delegate]];
|
184 |
editorToolbar = [[RdEditorToolbar alloc] initWithEditor:[self delegate]];
|
| 149 |
else
|
185 |
else
|
| 150 |
editorToolbar = [[REditorToolbar alloc] initWithEditor:[self delegate]];
|
186 |
editorToolbar = [[REditorToolbar alloc] initWithEditor:[self delegate]];
|
| 151 |
|
187 |
|
| 152 |
if(lineNumberingEnabled) {
|
- |
|
| 153 |
|
- |
|
| 154 |
SLog(@"RScriptEditorTextView: set up line numbering <%@>", self);
|
- |
|
| 155 |
|
- |
|
| 156 |
theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
|
- |
|
| 157 |
[scrollView setVerticalRulerView:theRulerView];
|
- |
|
| 158 |
[scrollView setHasHorizontalRuler:NO];
|
- |
|
| 159 |
[scrollView setHasVerticalRuler:YES];
|
- |
|
| 160 |
[scrollView setRulersVisible:YES];
|
- |
|
| 161 |
}
|
- |
|
| 162 |
[self setAllowsDocumentBackgroundColorChange:YES];
|
188 |
[self setAllowsDocumentBackgroundColorChange:YES];
|
| 163 |
[self setContinuousSpellCheckingEnabled:NO];
|
189 |
[self setContinuousSpellCheckingEnabled:NO];
|
| 164 |
|
190 |
|
| 165 |
if(![Preferences flagForKey:enableLineWrappingKey withDefault: YES])
|
191 |
if(![Preferences flagForKey:enableLineWrappingKey withDefault: YES])
|
| 166 |
[scrollView setHasHorizontalScroller:YES];
|
192 |
[scrollView setHasHorizontalScroller:YES];
|
| Line 169... |
Line 195... |
| 169 |
[self updateLineWrappingMode];
|
195 |
[self updateLineWrappingMode];
|
| 170 |
|
196 |
|
| 171 |
// Re-define tab stops for a better editing
|
197 |
// Re-define tab stops for a better editing
|
| 172 |
[self setTabStops];
|
198 |
[self setTabStops];
|
| 173 |
|
199 |
|
| 174 |
// disabled to get the current text range in textView safer
|
- |
|
| 175 |
[[self layoutManager] setBackgroundLayoutEnabled:NO];
|
- |
|
| 176 |
|
- |
|
| 177 |
// add NSViewBoundsDidChangeNotification to scrollView
|
200 |
// add NSViewBoundsDidChangeNotification to scrollView
|
| 178 |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundsDidChangeNotification:) name:NSViewBoundsDidChangeNotification object:[scrollView contentView]];
|
201 |
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(boundsDidChangeNotification:) name:NSViewBoundsDidChangeNotification object:[scrollView contentView]];
|
| 179 |
|
202 |
|
| 180 |
NSColor *c = [Preferences unarchivedObjectForKey:normalSyntaxColorKey withDefault:nil];
|
203 |
NSColor *c = [Preferences unarchivedObjectForKey:normalSyntaxColorKey withDefault:nil];
|
| 181 |
if (c) shColorNormal = c;
|
204 |
if (c) shColorNormal = c;
|
| Line 288... |
Line 311... |
| 288 |
[prefs addObserver:self forKeyPath:editorSelectionBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
|
311 |
[prefs addObserver:self forKeyPath:editorSelectionBackgroundColorKey options:NSKeyValueObservingOptionNew context:NULL];
|
| 289 |
|
312 |
|
| 290 |
[self setTextColor:shColorNormal];
|
313 |
[self setTextColor:shColorNormal];
|
| 291 |
[self setInsertionPointColor:shColorCursor];
|
314 |
[self setInsertionPointColor:shColorCursor];
|
| 292 |
|
315 |
|
| - |
|
316 |
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
| 293 |
theTextStorage = [self textStorage];
|
317 |
[[self layoutManager] setAllowsNonContiguousLayout:YES];
|
| - |
|
318 |
#endif
|
| - |
|
319 |
|
| - |
|
320 |
|
| 294 |
}
|
321 |
}
|
| 295 |
|
322 |
|
| 296 |
- (void)dealloc {
|
323 |
- (void)dealloc {
|
| 297 |
SLog(@"RScriptEditorTextView: dealloc <%@>", self);
|
324 |
SLog(@"RScriptEditorTextView: dealloc <%@>", self);
|
| 298 |
|
325 |
|
| - |
|
326 |
[theTextStorage release];
|
| - |
|
327 |
|
| 299 |
if(editorToolbar) [editorToolbar release];
|
328 |
if(editorToolbar) [editorToolbar release];
|
| 300 |
|
329 |
|
| 301 |
if(highlightColorAttr) [highlightColorAttr release];
|
330 |
if(highlightColorAttr) [highlightColorAttr release];
|
| 302 |
|
331 |
|
| 303 |
if(shColorNormal) [shColorNormal release];
|
332 |
if(shColorNormal) [shColorNormal release];
|
| Line 315... |
Line 344... |
| 315 |
// if(rdColorSection) [rdColorSection release];
|
344 |
// if(rdColorSection) [rdColorSection release];
|
| 316 |
// if(rdColorMacroArg) [rdColorMacroArg release];
|
345 |
// if(rdColorMacroArg) [rdColorMacroArg release];
|
| 317 |
// if(rdColorMacroGen) [rdColorMacroGen release];
|
346 |
// if(rdColorMacroGen) [rdColorMacroGen release];
|
| 318 |
// if(rdColorDirective) [rdColorDirective release];
|
347 |
// if(rdColorDirective) [rdColorDirective release];
|
| 319 |
|
348 |
|
| 320 |
if(theRulerView) [theRulerView release];
|
- |
|
| 321 |
|
- |
|
| 322 |
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
349 |
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
| 323 |
[[Preferences sharedPreferences] removeDependent:self];
|
350 |
[[Preferences sharedPreferences] removeDependent:self];
|
| 324 |
if(prefs) [prefs release];
|
351 |
if(prefs) [prefs release];
|
| 325 |
|
352 |
|
| 326 |
[super dealloc];
|
353 |
[super dealloc];
|
| Line 422... |
Line 449... |
| 422 |
[self updateLineWrappingMode];
|
449 |
[self updateLineWrappingMode];
|
| 423 |
[self setNeedsDisplayInRect:[self bounds]];
|
450 |
[self setNeedsDisplayInRect:[self bounds]];
|
| 424 |
|
451 |
|
| 425 |
} else if ([keyPath isEqualToString:showLineNumbersKey]) {
|
452 |
} else if ([keyPath isEqualToString:showLineNumbersKey]) {
|
| 426 |
lineNumberingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
|
453 |
lineNumberingEnabled = [[change objectForKey:NSKeyValueChangeNewKey] boolValue];
|
| 427 |
//TODO implement
|
- |
|
| 428 |
if(lineNumberingEnabled) {
|
454 |
if(lineNumberingEnabled) {
|
| 429 |
if(!theRulerView) {
|
- |
|
| 430 |
theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
|
455 |
NoodleLineNumberView *theRulerView = [[NoodleLineNumberView alloc] initWithScrollView:scrollView];
|
| 431 |
[scrollView setVerticalRulerView:theRulerView];
|
456 |
[scrollView setVerticalRulerView:theRulerView];
|
| 432 |
}
|
- |
|
| 433 |
[scrollView setHasHorizontalRuler:NO];
|
457 |
[scrollView setHasHorizontalRuler:NO];
|
| 434 |
[scrollView setHasVerticalRuler:YES];
|
458 |
[scrollView setHasVerticalRuler:YES];
|
| 435 |
[scrollView setRulersVisible:YES];
|
459 |
[scrollView setRulersVisible:YES];
|
| 436 |
} else {
|
- |
|
| 437 |
[theRulerView release];
|
460 |
[theRulerView release];
|
| 438 |
theRulerView = nil;
|
461 |
} else {
|
| 439 |
[scrollView setHasHorizontalRuler:NO];
|
462 |
[scrollView setHasHorizontalRuler:NO];
|
| 440 |
[scrollView setHasVerticalRuler:NO];
|
463 |
[scrollView setHasVerticalRuler:NO];
|
| 441 |
[scrollView setRulersVisible:NO];
|
464 |
[scrollView setRulersVisible:NO];
|
| 442 |
}
|
465 |
}
|
| 443 |
[self setNeedsDisplay:YES];
|
466 |
[self setNeedsDisplay:YES];
|
| Line 919... |
Line 942... |
| 919 |
|
942 |
|
| 920 |
}
|
943 |
}
|
| 921 |
|
944 |
|
| 922 |
}
|
945 |
}
|
| 923 |
|
946 |
|
| - |
|
947 |
#pragma mark -
|
| - |
|
948 |
#pragma mark folding
|
| - |
|
949 |
|
| - |
|
950 |
- (void)foldSelectedLines:(id)sender
|
| - |
|
951 |
{
|
| - |
|
952 |
|
| - |
|
953 |
NSRange r = [self selectedRange];
|
| - |
|
954 |
|
| - |
|
955 |
if(!r.length) return;
|
| - |
|
956 |
|
| - |
|
957 |
if([[self string] characterAtIndex:NSMaxRange(r)-1] == '\n')
|
| - |
|
958 |
r.length--;
|
| - |
|
959 |
|
| - |
|
960 |
if(!r.length) return;
|
| - |
|
961 |
|
| - |
|
962 |
[theTextStorage beginEditing];
|
| - |
|
963 |
[theTextStorage addAttribute:foldingAttributeName value:[NSNumber numberWithBool:YES] range:r];
|
| - |
|
964 |
[theTextStorage endEditing];
|
| - |
|
965 |
|
| - |
|
966 |
[self didChangeText];
|
| - |
|
967 |
if(lineNumberingEnabled)
|
| - |
|
968 |
[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
|
| - |
|
969 |
|
| - |
|
970 |
[self setSelectedRange:NSMakeRange(NSMaxRange(r), 0)];
|
| - |
|
971 |
[self scrollRangeToVisible:[self selectedRange]];
|
| - |
|
972 |
|
| - |
|
973 |
}
|
| - |
|
974 |
|
| - |
|
975 |
- (BOOL)unfoldLinesContainingCharacterAtIndex:(NSUInteger)charIndex
|
| - |
|
976 |
{
|
| - |
|
977 |
|
| - |
|
978 |
NSTextStorage *textStorage = [self textStorage];
|
| - |
|
979 |
NSRange range;
|
| - |
|
980 |
NSNumber *value = [textStorage attribute:foldingAttributeName atIndex:charIndex longestEffectiveRange:&range inRange:NSMakeRange(0, [textStorage length])];
|
| - |
|
981 |
|
| - |
|
982 |
if (value && [value boolValue] && [self shouldChangeTextInRange:range replacementString:nil]) {
|
| - |
|
983 |
[textStorage removeAttribute:foldingAttributeName range:range];
|
| - |
|
984 |
[self didChangeText];
|
| - |
|
985 |
[self setSelectedRange:NSMakeRange(NSMaxRange(range), 0)];
|
| - |
|
986 |
if(lineNumberingEnabled)
|
| - |
|
987 |
[[[self enclosingScrollView] verticalRulerView] performSelector:@selector(refresh) withObject:nil afterDelay:0.0f];
|
| - |
|
988 |
[self scrollRangeToVisible:[self selectedRange]];
|
| - |
|
989 |
return YES;
|
| - |
|
990 |
}
|
| - |
|
991 |
return NO;
|
| - |
|
992 |
}
|
| - |
|
993 |
|
| - |
|
994 |
// <TODO> enable for folding
|
| - |
|
995 |
// - (void)mouseDown:(NSEvent *)event
|
| - |
|
996 |
// {
|
| - |
|
997 |
//
|
| - |
|
998 |
// if(![theTextStorage isKindOfClass:[RScriptEditorTextStorage class]]) [super mouseDown:event];
|
| - |
|
999 |
//
|
| - |
|
1000 |
// NSUInteger glyphIndex = [layoutManager glyphIndexForPoint:[self convertPointFromBase:[event locationInWindow]] inTextContainer:[self textContainer]];
|
| - |
|
1001 |
// RScriptEditorLayoutManager *layoutManager = (RScriptEditorLayoutManager*)[self layoutManager];
|
| - |
|
1002 |
//
|
| - |
|
1003 |
// [theTextStorage setLineFoldingEnabled:YES];
|
| - |
|
1004 |
//
|
| - |
|
1005 |
// // trigger unfolding if inside foldingAttachmentCell
|
| - |
|
1006 |
// if (glyphIndex < [layoutManager numberOfGlyphs]) {
|
| - |
|
1007 |
// NSUInteger charIndex = [layoutManager characterIndexForGlyphAtIndex:glyphIndex];
|
| - |
|
1008 |
// NSRange range;
|
| - |
|
1009 |
// NSNumber *value = [theTextStorage attribute:foldingAttributeName atIndex:charIndex longestEffectiveRange:&range inRange:NSMakeRange(0, [theTextStorage length])];
|
| - |
|
1010 |
//
|
| - |
|
1011 |
// if (value && [value boolValue]) {
|
| - |
|
1012 |
// NSTextAttachment *attachment = [theTextStorage attribute:NSAttachmentAttributeName atIndex:range.location effectiveRange:NULL];
|
| - |
|
1013 |
//
|
| - |
|
1014 |
// if (attachment) {
|
| - |
|
1015 |
// NSTextAttachmentCell *cell = (NSTextAttachmentCell *)[attachment attachmentCell];
|
| - |
|
1016 |
// NSRect cellFrame;
|
| - |
|
1017 |
// NSPoint delta;
|
| - |
|
1018 |
//
|
| - |
|
1019 |
// glyphIndex = [layoutManager glyphIndexForCharacterAtIndex:range.location];
|
| - |
|
1020 |
//
|
| - |
|
1021 |
// cellFrame.origin = [self textContainerOrigin];
|
| - |
|
1022 |
// cellFrame.size = [layoutManager attachmentSizeForGlyphAtIndex:glyphIndex];
|
| - |
|
1023 |
//
|
| - |
|
1024 |
// delta = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRange:NULL].origin;
|
| - |
|
1025 |
// cellFrame.origin.x += delta.x;
|
| - |
|
1026 |
// cellFrame.origin.y += delta.y;
|
| - |
|
1027 |
//
|
| - |
|
1028 |
// cellFrame.origin.x += [layoutManager locationForGlyphAtIndex:glyphIndex].x;
|
| - |
|
1029 |
//
|
| - |
|
1030 |
// if ([cell wantsToTrackMouseForEvent:event inRect:cellFrame ofView:self atCharacterIndex:range.location] && [cell trackMouse:event inRect:cellFrame ofView:self atCharacterIndex:range.location untilMouseUp:YES]) return;
|
| - |
|
1031 |
// }
|
| - |
|
1032 |
// }
|
| - |
|
1033 |
// }
|
| - |
|
1034 |
//
|
| - |
|
1035 |
// [theTextStorage setLineFoldingEnabled:NO];
|
| - |
|
1036 |
//
|
| - |
|
1037 |
// [super mouseDown:event];
|
| - |
|
1038 |
// }
|
| - |
|
1039 |
|
| - |
|
1040 |
- (void)setTypingAttributes:(NSDictionary *)attrs
|
| - |
|
1041 |
{
|
| - |
|
1042 |
// we don't want to store foldingAttributeName as a typing attribute
|
| - |
|
1043 |
if ([attrs objectForKey:foldingAttributeName]) {
|
| - |
|
1044 |
NSMutableDictionary *copy = [[attrs mutableCopyWithZone:NULL] autorelease];
|
| - |
|
1045 |
[copy removeObjectForKey:foldingAttributeName];
|
| - |
|
1046 |
attrs = copy;
|
| - |
|
1047 |
}
|
| - |
|
1048 |
|
| - |
|
1049 |
[super setTypingAttributes:attrs];
|
| - |
|
1050 |
}
|
| - |
|
1051 |
|
| - |
|
1052 |
#pragma mark -
|
| - |
|
1053 |
|
| 924 |
- (void)updatePreferences
|
1054 |
- (void)updatePreferences
|
| 925 |
{
|
1055 |
{
|
| 926 |
|
1056 |
|
| 927 |
}
|
1057 |
}
|
| 928 |
@end
|
1058 |
@end
|