aboutsummaryrefslogtreecommitdiffstats
path: root/Source/SPNarrowDownCompletion.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2010-04-24 01:36:34 +0000
committerrowanbeentje <rowan@beent.je>2010-04-24 01:36:34 +0000
commita329d031aac349c0ad2b0768cc24ce69dc09a577 (patch)
tree12a58d877c97b742ecb9b00c8b707f9128543c42 /Source/SPNarrowDownCompletion.m
parentb7d6974ed6993727bd5bd39ec905c69eecb709b8 (diff)
downloadsequelpro-a329d031aac349c0ad2b0768cc24ce69dc09a577.tar.gz
sequelpro-a329d031aac349c0ad2b0768cc24ce69dc09a577.tar.bz2
sequelpro-a329d031aac349c0ad2b0768cc24ce69dc09a577.zip
Merge in a number of fixes from trunk (r2065, r2066, r2067, r2068, r2069, r2074, r2075, r2076, r2078, r2079, r2081, r2083, r2084, r2085, r2089, r2090, r2100, r2110, r2117, r2118, r2119, r2120, r2128, r2132, r2133, r2134, r2137, r2138, r2139, r2140, r2142, r2150, r2152, r2153, r2154, r2155, r2158, and r2160)
Diffstat (limited to 'Source/SPNarrowDownCompletion.m')
-rw-r--r--Source/SPNarrowDownCompletion.m192
1 files changed, 138 insertions, 54 deletions
diff --git a/Source/SPNarrowDownCompletion.m b/Source/SPNarrowDownCompletion.m
index e635958f..3bef11c8 100644
--- a/Source/SPNarrowDownCompletion.m
+++ b/Source/SPNarrowDownCompletion.m
@@ -61,6 +61,7 @@
- (BOOL)SP_NarrowDownCompletion_canHandleEvent:(NSEvent*)anEvent
{
+
NSInteger visibleRows = (NSInteger)floor(NSHeight([self visibleRect]) / ([self rowHeight]+[self intercellSpacing].height)) - 1;
struct { unichar key; NSInteger rows; } const key_movements[] =
@@ -74,9 +75,8 @@
};
unichar keyCode = 0;
- if([anEvent type] == NSScrollWheel)
- keyCode = [anEvent deltaY] >= 0.0 ? NSUpArrowFunctionKey : NSDownArrowFunctionKey;
- else if([anEvent type] == NSKeyDown && [[anEvent characters] length] == 1)
+
+ if([anEvent type] == NSKeyDown && [[anEvent characters] length] == 1)
keyCode = [[anEvent characters] characterAtIndex:0];
@@ -85,9 +85,14 @@
if(keyCode == key_movements[i].key)
{
NSInteger row = MAX(0, MIN([self selectedRow] + key_movements[i].rows, [self numberOfRows]-1));
- [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
- [self scrollRowToVisible:row];
+ if(row == 0 && ![[[self delegate] tableView:self selectionIndexesForProposedSelection:[NSIndexSet indexSetWithIndex:row]] containsIndex:0]) {
+ if(visibleRows > 1)
+ [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row+1] byExtendingSelection:NO];
+ } else {
+ [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
+ }
+ [self scrollRowToVisible:row];
return YES;
}
}
@@ -107,7 +112,7 @@
maxWindowWidth = 450;
- if(self = [super initWithContentRect:NSMakeRect(0,0,maxWindowWidth,0) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO])
+ if(self = [super initWithContentRect:NSMakeRect(0,0,maxWindowWidth,0) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES])
{
mutablePrefix = [NSMutableString new];
textualInputCharacters = [[NSMutableCharacterSet alphanumericCharacterSet] retain];
@@ -115,18 +120,23 @@
filtered = nil;
spaceCounter = 0;
currentSyncImage = 0;
+ staticPrefix = nil;
+ suggestions = nil;
+ commonPrefixWasInsertedByAutoComplete = NO;
prefs = [NSUserDefaults standardUserDefaults];
+ originalFilterString = [[NSMutableString alloc] init];
+ [originalFilterString setString:@""];
tableFont = [NSUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] dataForKey:SPCustomQueryEditorFont]];
[self setupInterface];
syncArrowImages = [[NSArray alloc] initWithObjects:
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_01" ofType:@"tiff"]],
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_02" ofType:@"tiff"]],
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_03" ofType:@"tiff"]],
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_04" ofType:@"tiff"]],
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_05" ofType:@"tiff"]],
- [[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_06" ofType:@"tiff"]],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_01" ofType:@"tiff"]] autorelease],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_02" ofType:@"tiff"]] autorelease],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_03" ofType:@"tiff"]] autorelease],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_04" ofType:@"tiff"]] autorelease],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_05" ofType:@"tiff"]] autorelease],
+ [[[NSImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"sync_arrows_06" ofType:@"tiff"]] autorelease],
nil];
}
@@ -135,15 +145,17 @@
- (void)dealloc
{
+ [NSObject cancelPreviousPerformRequestsWithTarget:self];
if(stateTimer != nil) {
[stateTimer invalidate];
[stateTimer release];
}
stateTimer = nil;
- [staticPrefix release];
+ if (staticPrefix) [staticPrefix release];
[mutablePrefix release];
[textualInputCharacters release];
-
+ [originalFilterString release];
+ if (syncArrowImages) [syncArrowImages release];
if(suggestions) [suggestions release];
if (filtered) [filtered release];
@@ -151,11 +163,21 @@
[super dealloc];
}
+- (void)close
+{
+ closeMe = YES;
+ [theView setCompletionIsOpen:NO];
+ [super close];
+}
+
- (void)updateSyncArrowStatus
{
+ // update sync arrow image
currentSyncImage++;
- timeCounter++;
if(currentSyncImage >= [syncArrowImages count]) currentSyncImage = 0;
+
+ // check if connection is still querying the db structure
+ timeCounter++;
if(timeCounter > 20) {
timeCounter = 0;
if(![[theView valueForKeyPath:@"mySQLConnection"] isQueryingDatabaseStructure]) {
@@ -165,7 +187,7 @@
[stateTimer release];
stateTimer = nil;
if(syncArrowImages) [syncArrowImages release];
- [self performSelectorOnMainThread:@selector(reInvokeCompletion) withObject:nil waitUntilDone:NO];
+ [self performSelectorOnMainThread:@selector(reInvokeCompletion) withObject:nil waitUntilDone:YES];
closeMe = YES;
return;
}
@@ -178,9 +200,14 @@
- (void)reInvokeCompletion
{
+ if(stateTimer) {
+ [stateTimer invalidate];
+ [stateTimer release];
+ stateTimer = nil;
+ }
[theView setCompletionIsOpen:NO];
- [theView doCompletionByUsingSpellChecker:dictMode fuzzyMode:fuzzyMode autoCompleteMode:NO];
[self close];
+ [theView performSelector:@selector(refreshCompletion) withObject:nil afterDelay:0.0];
}
- (id)initWithItems:(NSArray*)someSuggestions alreadyTyped:(NSString*)aUserString staticPrefix:(NSString*)aStaticPrefix
@@ -199,6 +226,10 @@
[mutablePrefix appendString:aUserString];
autoCompletionMode = autoComplete;
+
+ if(autoCompletionMode)
+ [originalFilterString appendString:aUserString];
+
oneColumnMode = oneColumn;
isQueryingDatabaseStructure = isQueryingDBStructure;
@@ -230,6 +261,8 @@
theView = aView;
dictMode = mode;
+ timeCounter = 0;
+
suggestions = [someSuggestions retain];
if(dictMode || oneColumnMode) {
@@ -306,13 +339,11 @@
theTableView = [[[NSTableView alloc] initWithFrame:NSZeroRect] autorelease];
[theTableView setFocusRingType:NSFocusRingTypeNone];
- [theTableView setAllowsEmptySelection:NO];
+ [theTableView setAllowsEmptySelection:YES];
[theTableView setHeaderView:nil];
- [theTableView setDelegate:self];
NSTableColumn *column0 = [[[NSTableColumn alloc] initWithIdentifier:@"image"] autorelease];
- [column0 setDataCell:[NSImageCell new]];
- // [column0 setEditable:NO];
+ [column0 setDataCell:[[NSImageCell new] autorelease]];
[theTableView addTableColumn:column0];
[column0 setMinWidth:0];
[column0 setWidth:20];
@@ -339,9 +370,11 @@
[column4 setWidth:95];
[theTableView setDataSource:self];
+ [theTableView setDelegate:self];
[scrollView setDocumentView:theTableView];
[self setContentView:scrollView];
+
}
// ========================
@@ -354,10 +387,10 @@
- (NSString *)tableView:(NSTableView *)aTableView toolTipForCell:(id)aCell rect:(NSRectPointer)rect tableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex mouseLocation:(NSPoint)mouseLocation
{
- if(isQueryingDatabaseStructure) rowIndex--;
-
if([[aTableColumn identifier] isEqualToString:@"image"]) {
- if(rowIndex == -1) return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+ if(isQueryingDatabaseStructure && rowIndex == 0)
+ return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+
if(!dictMode) {
NSString *imageName = [[filtered objectAtIndex:rowIndex] objectForKey:@"image"];
if([imageName hasPrefix:@"dummy"])
@@ -377,10 +410,14 @@
}
return @"";
} else if([[aTableColumn identifier] isEqualToString:@"name"]) {
- if(rowIndex == -1) return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+ if(isQueryingDatabaseStructure && rowIndex == 0)
+ return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+
return [[filtered objectAtIndex:rowIndex] objectForKey:@"display"];
} else if ([[aTableColumn identifier] isEqualToString:@"list"] || [[aTableColumn identifier] isEqualToString:@"type"]) {
- if(rowIndex == -1) return NSLocalizedString(@"fetching database structure data in progress", @"fetching database structure data in progress");
+ if(isQueryingDatabaseStructure && rowIndex == 0)
+ return NSLocalizedString(@"fetching database structure data in progress", @"fetching database structure data in progress");
+
if(dictMode) {
return @"";
} else {
@@ -399,7 +436,9 @@
}
} else if ([[aTableColumn identifier] isEqualToString:@"path"]) {
- if(rowIndex == -1) return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+ if(isQueryingDatabaseStructure && rowIndex == 0)
+ return NSLocalizedString(@"fetching database structure in progress", @"fetching database structure in progress");
+
if(dictMode) {
return @"";
} else {
@@ -419,25 +458,22 @@
return @"";
}
-- (BOOL)tableView:(NSTableView *)aTableView shouldSelectRow:(NSInteger)rowIndex
+- (NSIndexSet *)tableView:(NSTableView *)tableView selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes
{
- if(rowIndex == 0 && isQueryingDatabaseStructure)
- return NO;
+ if(isQueryingDatabaseStructure && [proposedSelectionIndexes containsIndex:0])
+ return [tableView selectedRowIndexes];
- return YES;
+ return proposedSelectionIndexes;
}
-
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex
{
NSImage* image = nil;
NSString* imageName = nil;
- if(isQueryingDatabaseStructure) rowIndex--;
-
if([[aTableColumn identifier] isEqualToString:@"image"]) {
if(!dictMode) {
- if(rowIndex == -1) {
+ if(isQueryingDatabaseStructure && rowIndex == 0) {
return [syncArrowImages objectAtIndex:currentSyncImage];
} else {
imageName = [[filtered objectAtIndex:rowIndex] objectForKey:@"image"];
@@ -450,11 +486,14 @@
} else if([[aTableColumn identifier] isEqualToString:@"name"]) {
[[aTableColumn dataCell] setFont:[NSFont systemFontOfSize:12]];
- if(rowIndex == -1) return @"fetching structure…";
+
+ if(isQueryingDatabaseStructure && rowIndex == 0)
+ return @"fetching structure…";
+
return [[filtered objectAtIndex:rowIndex] objectForKey:@"display"];
} else if ([[aTableColumn identifier] isEqualToString:@"list"]) {
- if(rowIndex == -1) {
+ if(isQueryingDatabaseStructure && rowIndex == 0) {
NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease];
[b setPullsDown:NO];
[b setArrowPosition:NSPopUpNoArrow];
@@ -491,7 +530,7 @@
}
} else if([[aTableColumn identifier] isEqualToString:@"type"]) {
- if(rowIndex == -1) {
+ if(isQueryingDatabaseStructure && rowIndex == 0) {
return @"";
}
if(dictMode) {
@@ -506,7 +545,7 @@
}
} else if ([[aTableColumn identifier] isEqualToString:@"path"]) {
- if(rowIndex == -1) {
+ if(isQueryingDatabaseStructure && rowIndex == 0) {
NSPopUpButtonCell *b = [[NSPopUpButtonCell new] autorelease];
[b setPullsDown:NO];
[b setArrowPosition:NSPopUpNoArrow];
@@ -570,6 +609,7 @@
{
NSMutableArray* newFiltered = [[NSMutableArray alloc] initWithCapacity:5];
+
if([mutablePrefix length] > 0)
{
if(dictMode) {
@@ -653,6 +693,11 @@
return;
}
+
+ // if fetching db structure add dummy row for displaying that info on top of the list
+ if(isQueryingDatabaseStructure)
+ [newFiltered insertObject:[NSDictionary dictionaryWithObjectsAndKeys:@"dummy", @"display", @"", @"noCompletion", nil] atIndex:0];
+
NSPoint old = NSMakePoint([self frame].origin.x, [self frame].origin.y + [self frame].size.height);
NSInteger displayedRows = [newFiltered count] < SPNarrowDownCompletionMaxRows ? [newFiltered count] : SPNarrowDownCompletionMaxRows;
@@ -676,6 +721,7 @@
if(!dictMode)
[self checkSpaceForAllowedCharacter];
[theTableView reloadData];
+ [theTableView selectRowIndexes:[NSIndexSet indexSetWithIndex:(isQueryingDatabaseStructure)?1:0] byExtendingSelection:NO];
}
// =========================
@@ -724,6 +770,9 @@
if(!event)
continue;
+ // Exit if closeMe has been set in the meantime
+ if(closeMe) return;
+
NSEventType t = [event type];
if([theTableView SP_NarrowDownCompletion_canHandleEvent:event])
{
@@ -738,6 +787,16 @@
// e.g. for US keyboard "⌥u a" to insert ä
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;
+ }
+ }
[NSApp sendEvent: event];
if(commaInsertionMode)
@@ -760,6 +819,15 @@
[theTableView setBackgroundColor:[NSColor colorWithCalibratedRed:0.9f green:0.9f blue:0.9f alpha:1.0f]];
[self filter];
} else {
+ if(autoCompletionMode) {
+ if(commonPrefixWasInsertedByAutoComplete) {
+ [theView setSelectedRange:theCharRange];
+ [theView insertText:originalFilterString];
+ }
+ [theView setCompletionIsOpen:NO];
+ [self close];
+ break;
+ }
if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)];
break;
}
@@ -770,6 +838,14 @@
}
else if(key == NSBackspaceCharacter || key == NSDeleteCharacter)
{
+ if(autoCompletionMode) {
+ if(commonPrefixWasInsertedByAutoComplete) {
+ [theView setSelectedRange:theCharRange];
+ [theView insertText:originalFilterString];
+ }
+ [NSApp sendEvent:event];
+ break;
+ }
[NSApp sendEvent:event];
if([mutablePrefix length] == 0 || commaInsertionMode)
break;
@@ -782,6 +858,18 @@
}
else if([textualInputCharacters characterIsMember:key])
{
+
+ if(autoCompletionMode) {
+ [theView setCompletionIsOpen:NO];
+ [self close];
+ if(commonPrefixWasInsertedByAutoComplete) {
+ [theView setSelectedRange:theCharRange];
+ [theView insertText:originalFilterString];
+ }
+ [NSApp sendEvent:event];
+ return;
+ }
+
[NSApp sendEvent:event];
if(commaInsertionMode)
@@ -808,11 +896,18 @@
if(([event clickCount] == 2)) {
[self completeAndInsertSnippet];
} else {
- [NSApp sendEvent:event];
if(!NSPointInRect([NSEvent mouseLocation], [self frame])) {
+ if(autoCompletionMode) {
+ if(commonPrefixWasInsertedByAutoComplete) {
+ [theView setSelectedRange:theCharRange];
+ [theView insertText:originalFilterString];
+ }
+ }
if(cursorMovedLeft) [theView performSelector:@selector(moveRight:)];
+ [NSApp sendEvent:event];
break;
}
+ [NSApp sendEvent:event];
}
}
else
@@ -860,6 +955,7 @@
theCharRange.length += [toInsert length];
theParseRange.length += [toInsert length];
[theView insertText:[toInsert lowercaseString]];
+ commonPrefixWasInsertedByAutoComplete = YES;
[self checkSpaceForAllowedCharacter];
}
}
@@ -895,17 +991,7 @@
{
if([theTableView selectedRow] == -1) return;
- NSDictionary* selectedItem;
- NSInteger selectedRowNumber = [theTableView selectedRow];
- if(isQueryingDatabaseStructure) {
- if(selectedRowNumber < 1) {
- closeMe = YES;
- return;
- }
- selectedItem = [filtered objectAtIndex:selectedRowNumber-1];
- } else {
- selectedItem = [filtered objectAtIndex:selectedRowNumber];
- }
+ NSDictionary *selectedItem = [filtered objectAtIndex:[theTableView selectedRow]];
if([selectedItem objectForKey:@"noCompletion"]) {
closeMe = YES;
@@ -919,9 +1005,7 @@
if([selectedItem objectForKey:@"isRef"]
&& ([[NSApp currentEvent] modifierFlags] & (NSShiftKeyMask))
&& [[selectedItem objectForKey:@"path"] length]) {
- // NSString *path = [NSString stringWithFormat:@"%@.%@",
- // [[[selectedItem objectForKey:@"path"] componentsSeparatedByString:SPUniqueSchemaDelimiter] componentsJoinedByPeriodAndBacktickQuotedAndIgnoreFirst],
- // [candidateMatch backtickQuotedString]];
+
NSString *path = [[[selectedItem objectForKey:@"path"] componentsSeparatedByString:SPUniqueSchemaDelimiter] componentsJoinedByPeriodAndBacktickQuotedAndIgnoreFirst];
// Check if path's db name is the current selected db name