diff --git a/ChangeLog b/ChangeLog index 2eec1af..b00c7ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2021-11-26 Riccardo Mottola + + * Modules/Editors/ProjectCenter/PCEditor.m + Do not send double computeNewParenthesisNesting: on key pressed. + Furthermore, use a timer so that in case of rapid re-computing + it gets invalidated before and only calculated at the last event. + 2021-10-19 Riccardo Mottola * Modules/Editors/ProjectCenter/PCEditorView.h diff --git a/Modules/Editors/ProjectCenter/PCEditor.h b/Modules/Editors/ProjectCenter/PCEditor.h index 96f97f4..5e24d64 100644 --- a/Modules/Editors/ProjectCenter/PCEditor.h +++ b/Modules/Editors/ProjectCenter/PCEditor.h @@ -73,21 +73,11 @@ NSColor *highlightColor; NSColor *backgroundColor; NSColor *readOnlyColor; - NSColor *textBackground; - - // location of the highlit delimiter character - unsigned int highlitCharacterLocation; + NSColor *textBackgroundColor; - // is YES if we are currently highlighting a delimiter character - // otherwise NO - BOOL isCharacterHighlit; - int highlited_chars[2]; - - // the stored color and font attributes of the highlit character, so - // that they can be restored later on when the character is un-highlit - NSColor *previousFGColor; - NSColor *previousBGColor; - NSColor *previousFont; + // location of the highlighted delimiter characters + // NSNotFound means not set + NSUInteger highlighted_chars[2]; // This is used to protect that -textViewDidChangeSelection: invocations // don't do anything when the text view changing, because this causes @@ -95,6 +85,9 @@ // of this method. BOOL editorTextViewIsPressingKey; + // Slightly delay drawing of highlit parentheses + NSTimer *phlTimer; + // keep one undo manager for the editor NSUndoManager *undoManager; } @@ -151,7 +144,7 @@ @interface PCEditor (Parenthesis) - (void)unhighlightCharacter: (NSTextView *)editorView; -- (void)highlightCharacterAt:(NSUInteger)location inEditor: (NSTextView *)editorView; +- (void)highlightCharacterPair: (NSTextView *)editorView; - (void)computeNewParenthesisNesting: (NSTextView *)editorView; @end diff --git a/Modules/Editors/ProjectCenter/PCEditor.m b/Modules/Editors/ProjectCenter/PCEditor.m index 2c93504..aa8769f 100644 --- a/Modules/Editors/ProjectCenter/PCEditor.m +++ b/Modules/Editors/ProjectCenter/PCEditor.m @@ -136,7 +136,7 @@ RELEASE(lm); ev = [[PCEditorView alloc] initWithFrame:fr textContainer:tc]; - [ev setBackgroundColor:textBackground]; + [ev setBackgroundColor:textBackgroundColor]; [ev setTextColor:textColor]; [ev setEditor:self]; if (_highlightSyntax) @@ -175,18 +175,14 @@ // Activate undo [ev setAllowsUndo: YES]; + [ev setDelegate:self]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChange:) name:NSTextDidChangeNotification object:ev]; - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(textViewDidChangeSelection:) - name:NSTextViewDidChangeSelectionNotification - object:ev]; - return ev; } @@ -222,14 +218,9 @@ ASSIGN(textColor, [NSColor blackColor]); ASSIGN(backgroundColor, [NSColor whiteColor]); ASSIGN(readOnlyColor, [NSColor lightGrayColor]); - - previousFGColor = nil; - previousBGColor = nil; - previousFont = nil; - isCharacterHighlit = NO; - highlited_chars[0] = -1; - highlited_chars[1] = -1; + highlighted_chars[0] = NSNotFound; + highlighted_chars[1] = NSNotFound; undoManager = [[NSUndoManager alloc] init]; } @@ -312,17 +303,17 @@ NSColor *col; col = [prefs colorForKey:EditorBackgroundColor defaultValue:backgroundColor]; - textBackground = col; + textBackgroundColor = col; } else { - textBackground = readOnlyColor; + textBackgroundColor = readOnlyColor; } textColor = [prefs colorForKey:EditorForegroundColor defaultValue:textColor]; [attributes setObject:font forKey:NSFontAttributeName]; - [attributes setObject:textBackground forKey:NSBackgroundColorAttributeName]; + [attributes setObject:textBackgroundColor forKey:NSBackgroundColorAttributeName]; [attributes setObject:textColor forKey:NSForegroundColorAttributeName]; [attributes setObject:[NSNumber numberWithInt: 0] // disable ligatures forKey:NSLigatureAttributeName]; @@ -948,21 +939,29 @@ } } +- (NSRange)textView:(NSTextView *)textView +willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange + toCharacterRange:(NSRange)newSelectedCharRange +{ + NSDebugLog(@"Will change selection from %@ to %@", NSStringFromRange(oldSelectedCharRange), NSStringFromRange(newSelectedCharRange)); + + if (editorTextViewIsPressingKey == NO) + { + // unhighlight also invalidates old locations + if (textView == _intEditorView || textView == _extEditorView) + [self unhighlightCharacter: textView]; + } + + return newSelectedCharRange; +} + - (void)textViewDidChangeSelection:(NSNotification *)notification { id object; object = [notification object]; - if (editorTextViewIsPressingKey == NO) - { - id object; - - object = [notification object]; - if (object == _intEditorView || object == _extEditorView) - [self computeNewParenthesisNesting: object]; - } - + NSDebugLog(@"received textViewDidChangeSelection notification"); // calculate current line if ([object isKindOfClass:[NSTextView class]]) { @@ -996,14 +995,13 @@ selLine = nlCount + 1; } - NSLog(@"%u corresponds to %u", selection.location, selLine); + NSLog(@"%u corresponds to %u", (unsigned int)selection.location, (unsigned int)selLine); } } - (void)editorTextViewWillPressKey:sender { editorTextViewIsPressingKey = YES; -// NSLog(@"Will pressing key"); if (sender == _intEditorView || sender == _extEditorView) [self unhighlightCharacter: sender]; @@ -1013,9 +1011,20 @@ - (void)editorTextViewDidPressKey:sender { -// NSLog(@"Did pressing key"); if (sender == _intEditorView || sender == _extEditorView) - [self computeNewParenthesisNesting: sender]; + { + if (nil != phlTimer) + { + [phlTimer invalidate]; + phlTimer = nil; + } + + phlTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 + target:self + selector:@selector(computeNewParenthesisNestingFromTimer:) + userInfo:sender + repeats:NO]; + } else NSLog(@"PCEditor: unexpected sender"); @@ -1356,112 +1365,56 @@ NSUInteger FindDelimiterInString(NSString * string, - (void)unhighlightCharacter: (NSTextView *)editorView { - int i; + unsigned i; NSTextStorage *textStorage = [editorView textStorage]; [textStorage beginEditing]; -// if (isCharacterHighlit) - for (i = 0; i < 2 && highlited_chars[i] != -1; i++) + for (i = 0; i < 2; i++) { - NSRange r = NSMakeRange(highlited_chars[i], 1); -// NSRange r = NSMakeRange(highlitCharacterLocation, i); + if (highlighted_chars[i] == NSNotFound) + continue; + NSRange r = NSMakeRange(highlighted_chars[i], 1); - isCharacterHighlit = NO; + [textStorage addAttribute:NSBackgroundColorAttributeName + value:textBackgroundColor + range:r]; - // restore the character's color and font attributes - if (previousFont != nil) - { - [textStorage addAttribute:NSFontAttributeName - value:previousFont - range:r]; - } - else - { - [textStorage removeAttribute:NSFontAttributeName range:r]; - } - - if (previousFGColor != nil) - { - [textStorage addAttribute:NSForegroundColorAttributeName - value:previousFGColor - range:r]; - } - else - { - [textStorage removeAttribute:NSForegroundColorAttributeName - range:r]; - } - - if (previousBGColor != nil) - { - [textStorage addAttribute:NSBackgroundColorAttributeName - value:previousBGColor - range:r]; - } - else - { - [textStorage removeAttribute:NSBackgroundColorAttributeName - range:r]; - } - - highlited_chars[i] = -1; + highlighted_chars[i] = NSNotFound; } [textStorage endEditing]; } -- (void)highlightCharacterAt:(NSUInteger)location inEditor: (NSTextView *)editorView +- (void)highlightCharacterPair:(NSTextView *)editorView { - int i; + unsigned i; + NSTextStorage *textStorage = [editorView textStorage]; - for (i = 0; i < 2 && highlited_chars[i] != -1; i++) {}; + [textStorage beginEditing]; -// if (isCharacterHighlit == NO) - if (i < 2) + for (i = 0; i < 2; i++) { - NSTextStorage *textStorage = [editorView textStorage]; - NSRange r = NSMakeRange(location, 1); - NSRange tmp; + if (highlighted_chars[i] == NSNotFound) + continue; -// NSLog(@"highlight"); + NSRange r = NSMakeRange(highlighted_chars[i], 1); -// highlitCharacterLocation = location; - highlited_chars[i] = location; - - isCharacterHighlit = YES; NSAssert(textStorage, @"textstorage can't be nil"); - [textStorage beginEditing]; - // store the previous character's attributes - ASSIGN(previousFGColor, - [textStorage attribute:NSForegroundColorAttributeName - atIndex:location - effectiveRange:&tmp]); - ASSIGN(previousBGColor, - [textStorage attribute:NSBackgroundColorAttributeName - atIndex:location - effectiveRange:&tmp]); - ASSIGN(previousFont, [textStorage attribute:NSFontAttributeName - atIndex:location - effectiveRange:&tmp]); - - [textStorage addAttribute:NSFontAttributeName - value:highlightFont - range:r]; [textStorage addAttribute:NSBackgroundColorAttributeName value:highlightColor range:r]; -/* [textStorage addAttribute:NSForegroundColorAttributeName - value:highlightColor - range:r]; - [textStorage removeAttribute:NSBackgroundColorAttributeName - range:r];*/ - - [textStorage endEditing]; } + [textStorage endEditing]; +} + +- (void)computeNewParenthesisNestingFromTimer:(NSTimer *)timer +{ + phlTimer = nil; + [self computeNewParenthesisNesting:[timer userInfo]]; } - (void)computeNewParenthesisNesting: (NSTextView *)editorView @@ -1477,7 +1430,8 @@ NSUInteger FindDelimiterInString(NSString * string, NSAssert(editorView, @"computeNewParenthesis: editorView is nil"); selectedRange = [editorView selectedRange]; - // make sure we un-highlight a previously highlit delimiter + // make sure we un-highlit a previously highlit delimiter + // should normally be already un-highlit by will change notif. [self unhighlightCharacter :editorView]; // if we have a character at the selected location, check @@ -1508,8 +1462,9 @@ NSUInteger FindDelimiterInString(NSString * string, // and in case a delimiter is found, highlight it if (result != NSNotFound) { - [self highlightCharacterAt:selectedRange.location inEditor:editorView]; - [self highlightCharacterAt:result inEditor:editorView]; + highlighted_chars[0] = selectedRange.location; + highlighted_chars[1] = result; + [self highlightCharacterPair :editorView]; } } }