diff options
author | rowanbeentje <rowan@beent.je> | 2010-11-30 02:24:42 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2010-11-30 02:24:42 +0000 |
commit | b4a5f241c7a6adfdf1b8f4afb94f8d8c57a5c0a9 (patch) | |
tree | f1f58eb63be0f13a653b9ecd0174264e0707ffa6 /Source/SPNarrowDownCompletion.m | |
parent | cc2e00c656a34d4c472a25f929282c8fc63d0174 (diff) | |
download | sequelpro-b4a5f241c7a6adfdf1b8f4afb94f8d8c57a5c0a9.tar.gz sequelpro-b4a5f241c7a6adfdf1b8f4afb94f8d8c57a5c0a9.tar.bz2 sequelpro-b4a5f241c7a6adfdf1b8f4afb94f8d8c57a5c0a9.zip |
- Rework insertCommonPrefix to insertAutocompletePlaceholder, implementing a more Mac-like behaviour: insert a faded placeholder for the currently selected autocomplete item.
- Update the autocomplete placeholder when the autocomplete dropdown selection is changed
- Clean up methods for removing placeholders, and ensure the placeholder is always removed (fixes issues with pasting with a placeholder visible, etc)
- When the Help window is closed, switch off AutoHelp - this will aid in supporting those users who accidentally switch on AutoHelp and then can't figure out how to switch it off, resulting in returning windows.
Diffstat (limited to 'Source/SPNarrowDownCompletion.m')
-rw-r--r-- | Source/SPNarrowDownCompletion.m | 117 |
1 files changed, 69 insertions, 48 deletions
diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m index d83f78c5..a960e74a 100644 --- a/Source/SPNarrowDownCompletion.m +++ b/Source/SPNarrowDownCompletion.m @@ -35,6 +35,12 @@ #import "RegexKitLite.h" #import "SPTextView.h" +#pragma mark - +#pragma mark attribute definition + +#define kSPAutoCompletePlaceholderName @"Placeholder" +#define kSPAutoCompletePlaceholderVal @"placholder" + @interface NSTableView (MovingSelectedRow) - (BOOL)SP_NarrowDownCompletion_canHandleEvent:(NSEvent*)anEvent; @@ -47,7 +53,7 @@ - (NSString*)filterString; - (void)setupInterface; - (void)filter; -- (void)insertCommonPrefix; +- (void)insertAutocompletePlaceholder; - (void)completeAndInsertSnippet; @end @@ -86,6 +92,7 @@ [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; } [self scrollRowToVisible:row]; + [[self delegate] insertAutocompletePlaceholder]; return YES; } } @@ -115,7 +122,7 @@ currentSyncImage = 0; staticPrefix = nil; suggestions = nil; - commonPrefixWasInsertedByAutoComplete = NO; + autocompletePlaceholderWasInserted = NO; prefs = [NSUserDefaults standardUserDefaults]; originalFilterString = [[NSMutableString alloc] init]; [originalFilterString setString:@""]; @@ -794,14 +801,11 @@ if (([event modifierFlags] & (NSShiftKeyMask|NSControlKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) == NSAlternateKeyMask || [[event characters] length] == 0) { if(autoCompletionMode) { - if(commonPrefixWasInsertedByAutoComplete) { - [theView setSelectedRange:theCharRange]; - [theView insertText:originalFilterString]; - [theView setCompletionIsOpen:NO]; - [self close]; - [NSApp sendEvent:event]; - break; - } + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; + [theView setCompletionIsOpen:NO]; + [self close]; + [NSApp sendEvent:event]; + break; } [NSApp sendEvent: event]; @@ -826,10 +830,7 @@ [self filter]; } else { if(autoCompletionMode) { - if(commonPrefixWasInsertedByAutoComplete) { - [theView setSelectedRange:theCharRange]; - [theView insertText:originalFilterString]; - } + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; [theView setCompletionIsOpen:NO]; [self close]; break; @@ -845,10 +846,7 @@ else if(key == NSBackspaceCharacter || key == NSDeleteCharacter) { if(autoCompletionMode) { - if(commonPrefixWasInsertedByAutoComplete) { - [theView setSelectedRange:theCharRange]; - [theView insertText:originalFilterString]; - } + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; [NSApp sendEvent:event]; break; } @@ -868,10 +866,7 @@ if(autoCompletionMode) { [theView setCompletionIsOpen:NO]; [self close]; - if(commonPrefixWasInsertedByAutoComplete) { - [theView setSelectedRange:theCharRange]; - [theView insertText:originalFilterString]; - } + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; [NSApp sendEvent:event]; return; } @@ -887,7 +882,7 @@ theCharRange.length++; theParseRange.length++; [self filter]; - [self insertCommonPrefix]; + [self insertAutocompletePlaceholder]; } else @@ -904,10 +899,7 @@ } else { if(!NSPointInRect([NSEvent mouseLocation], [self frame])) { if(autoCompletionMode) { - if(commonPrefixWasInsertedByAutoComplete) { - [theView setSelectedRange:theCharRange]; - [theView insertText:originalFilterString]; - } + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; } if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)]; [NSApp sendEvent:event]; @@ -921,6 +913,34 @@ [NSApp sendEvent:event]; } } + + // If the autocomplete menu is open, but the placeholder is still present, it needs removing. + if (autoCompletionMode && autocompletePlaceholderWasInserted) { + [[theView textStorage] beginEditing]; + NSRange attributeResultRange; + while (1) { + attributeResultRange = NSMakeRange(NSNotFound, 0); + if ([[theView textStorage] attribute:kSPAutoCompletePlaceholderName atIndex:0 longestEffectiveRange:&attributeResultRange inRange:NSMakeRange(0, [[theView textStorage] length])]) { + + // A match was found - attributeResultRange contains the range of the attributed string + [[theView textStorage] deleteCharactersInRange:attributeResultRange]; + } else { + + // No match was found. attributeResultRange contains the range of the no match - this can be + // checked to see whether a match is inside the full range. + if (attributeResultRange.length == [[theView textStorage] length]) break; + + // A match was found - retrieve the location + NSUInteger matchStart = attributeResultRange.location+attributeResultRange.length; + if ([[theView textStorage] attribute:kSPAutoCompletePlaceholderName atIndex:matchStart longestEffectiveRange:&attributeResultRange inRange:NSMakeRange(matchStart, [[theView textStorage] length] - matchStart)]) { + [[theView textStorage] deleteCharactersInRange:attributeResultRange]; + } + } + } + [[theView textStorage] endEditing]; + autocompletePlaceholderWasInserted = NO; + } + [theView setCompletionIsOpen:NO]; [self close]; usleep(70); // tiny delay to suppress while continously pressing of ESC overlapping @@ -929,49 +949,50 @@ // ================== // = Action methods = // ================== -- (void)insertCommonPrefix +- (void)insertAutocompletePlaceholder { - if([theTableView selectedRow] == -1 || fuzzyMode) return; - id cur = [filtered objectAtIndex:0]; + // Clear any current placeholder + if (autocompletePlaceholderWasInserted) [self removeAutocompletionPlaceholder]; - if([cur objectForKey:@"noCompletion"]) return; + // Select the highlighted item in the list of suggestions + id cur = [filtered objectAtIndex:[theTableView selectedRow]]; + // Ensure it's a valid suggestion and extract the string + if ([cur objectForKey:@"noCompletion"]) return; NSString* curMatch = [cur objectForKey:@"match"] ?: [cur objectForKey:@"display"]; + if (![curMatch length]) return; - if(![curMatch length]) return; - - NSMutableString *commonPrefix = [NSMutableString string]; - [commonPrefix setString:curMatch]; - for(id candidate in filtered) { - NSString* candidateMatch; - candidateMatch = [candidate objectForKey:@"match"] ?: [candidate objectForKey:@"display"]; - NSString *tempPrefix = [candidateMatch commonPrefixWithString:commonPrefix options:NSCaseInsensitiveSearch]; - // if(![tempPrefix length]) break; - if([commonPrefix length] > [tempPrefix length]) - [commonPrefix setString:tempPrefix]; - } - - // Insert common prefix automatically - if([[self filterString] length] < [commonPrefix length]) { + // Insert a placeholder for the string in the textview + if ([originalFilterString length] < [curMatch length]) { NSUInteger currentSelectionPosition = [theView selectedRange].location; - NSString* toInsert = [commonPrefix substringFromIndex:[[self filterString] length]]; + NSString* toInsert = [curMatch substringFromIndex:[originalFilterString length]]; [mutablePrefix appendString:toInsert]; theCharRange.length += [toInsert length]; theParseRange.length += [toInsert length]; [theView insertText:[toInsert lowercaseString]]; - commonPrefixWasInsertedByAutoComplete = YES; + autocompletePlaceholderWasInserted = YES; // Restore the text selection location, and clearly mark the autosuggested text [theView setSelectedRange:NSMakeRange(currentSelectionPosition, 0)]; NSMutableAttributedStringAddAttributeValueRange([theView textStorage], NSForegroundColorAttributeName, [[theView otherTextColor] colorWithAlphaComponent:0.3], NSMakeRange(currentSelectionPosition, [toInsert length])); + NSMutableAttributedStringAddAttributeValueRange([theView textStorage], kSPAutoCompletePlaceholderName, kSPAutoCompletePlaceholderVal, NSMakeRange(currentSelectionPosition, [toInsert length])); [self checkSpaceForAllowedCharacter]; } } +- (void)removeAutocompletionPlaceholder +{ + if (!autocompletePlaceholderWasInserted) return; + + [theView setSelectedRange:theCharRange]; + [theView insertText:originalFilterString]; + autocompletePlaceholderWasInserted = NO; +} + - (void)insert_text:(NSString* )aString { |