diff options
author | rowanbeentje <rowan@beent.je> | 2009-12-08 01:38:13 +0000 |
---|---|---|
committer | rowanbeentje <rowan@beent.je> | 2009-12-08 01:38:13 +0000 |
commit | c71309b319ec4ea254ed5d6efd12fd7766fc5184 (patch) | |
tree | c1fcf3e5820103064656c34282051a2add5f3efb /Source | |
parent | 0483d38f13410bcf5dd81f38cf7a1c801b5f7271 (diff) | |
download | sequelpro-c71309b319ec4ea254ed5d6efd12fd7766fc5184.tar.gz sequelpro-c71309b319ec4ea254ed5d6efd12fd7766fc5184.tar.bz2 sequelpro-c71309b319ec4ea254ed5d6efd12fd7766fc5184.zip |
- Tweak positioning of old "working" spinner to center and align it
- Fix pagination to not enable the "next page" arrow when looking at a small, complete, filtered result
- Move content table setup and drawing to a new method called on the main thread. Should improve thread safety, and fixes flickering updates. Tweak a few bits of drawing code to take advantage of main thread status to further reduce flicker and jumping
Diffstat (limited to 'Source')
-rw-r--r-- | Source/TableContent.m | 168 |
1 files changed, 103 insertions, 65 deletions
diff --git a/Source/TableContent.m b/Source/TableContent.m index 7fcb284b..98de0278 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -168,26 +168,107 @@ */ - (void)loadTable:(NSString *)aTable { + + // Abort the reload if the user is still editing a row + if ( isEditingRow ) + return; + + // If no table has been supplied, clear the table interface and return + if (!aTable || [aTable isEqualToString:@""]) { + [self performSelectorOnMainThread:@selector(setTableDetails:) withObject:nil waitUntilDone:YES]; + return; + } + + // Attempt to retrieve the table encoding; if that fails (indicating an error occurred + // while retrieving table data), or if the Rows variable is null, clear and return + if (![tableDataInstance tableEncoding] || [[[tableDataInstance statusValues] objectForKey:@"Rows"] isNSNull]) { + [self performSelectorOnMainThread:@selector(setTableDetails:) withObject:nil waitUntilDone:YES]; + return; + } + + // Post a notification that a query will be performed + [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance]; + + // Set up the table details for the new table, and trigger an interface update + NSDictionary *tableDetails = [NSDictionary dictionaryWithObjectsAndKeys: + aTable, @"name", + [tableDataInstance columns], @"columns", + [tableDataInstance columnNames], @"columnNames", + [tableDataInstance getConstraints], @"constraints", + nil]; + [self performSelectorOnMainThread:@selector(setTableDetails:) withObject:tableDetails waitUntilDone:YES]; + + // Trigger a data refresh + [self loadTableValues]; + + // Restore the view origin if appropriate + if (!NSEqualRects(selectionViewportToRestore, NSZeroRect)) { + + // Scroll the viewport to the saved location + selectionViewportToRestore.size = [tableContentView visibleRect].size; + [tableContentView scrollRectToVisible:selectionViewportToRestore]; + } + + // Restore selection indexes if appropriate + if (selectionIndexToRestore) { + BOOL previousTableRowsSelectable = tableRowsSelectable; + tableRowsSelectable = YES; + [tableContentView selectRowIndexes:selectionIndexToRestore byExtendingSelection:NO]; + tableRowsSelectable = previousTableRowsSelectable; + } + + // Update display if necessary + [tableContentView performSelectorOnMainThread:@selector(displayIfNeeded) withObject:nil waitUntilDone:NO]; + + // Init copyTable with necessary information for copying selected rows as SQL INSERT + [tableContentView setTableInstance:self withTableData:tableValues withColumns:dataColumns withTableName:selectedTable withConnection:mySQLConnection]; + + // Post the notification that the query is finished + [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; + + // Clear any details to restore now that they have been restored + [self clearDetailsToRestore]; +} + +/** + * Update stored table details and update the interface to match the supplied + * table details. + * Should be called on the main thread. + */ +- (void) setTableDetails:(NSDictionary *)tableDetails +{ + NSString *newTableName; NSInteger i; NSNumber *colWidth, *sortColumnNumberToRestore = nil; NSArray *columnNames; NSDictionary *columnDefinition; NSTableColumn *theCol; BOOL enableInteraction = ![[tableDocumentInstance selectedToolbarItemIdentifier] isEqualToString:MAIN_TOOLBAR_TABLE_CONTENT] || ![tableDocumentInstance isWorking]; - [self performSelectorOnMainThread:@selector(setPaginationViewVisibility:) withObject:nil waitUntilDone:NO]; - // Abort the reload if the user is still editing a row - if ( isEditingRow ) - return; + if (!tableDetails) { + newTableName = nil; + } else { + newTableName = [tableDetails objectForKey:@"name"]; + } + + // Ensure the pagination view hides itself if visible, after a tiny delay for smoothness + [self performSelector:@selector(setPaginationViewVisibility:) withObject:nil afterDelay:0.1]; + + // Reset table key store for use in argumentForRow: + if (keys) [keys release], keys = nil; + + // Reset data column store + [dataColumns removeAllObjects]; // Check the supplied table name. If it matches the old one, a reload is being performed; // reload the data in-place to maintain table state if possible. - if ([selectedTable isEqualToString:aTable]) { + if ([selectedTable isEqualToString:newTableName]) { previousTableRowsCount = tableRowsCount; // Otherwise store the newly selected table name and reset the data } else { - selectedTable = aTable; + if (selectedTable) [selectedTable release], selectedTable = nil; + if (newTableName) selectedTable = [[NSString alloc] initWithString:newTableName]; previousTableRowsCount = 0; contentPage = 1; [paginationPageField setStringValue:@"1"]; @@ -200,17 +281,8 @@ [tableContentView scrollColumnToVisible:0]; } - // Reset table key store for use in argumentForRow: - if (keys) [keys release], keys = nil; - - // Reset data column store - [dataColumns removeAllObjects]; - // If no table has been supplied, reset the view to a blank table and disabled elements. - // [tableDataInstance tableEncoding] == nil indicates that an error occured while retrieving table data - if ( [[[tableDataInstance statusValues] objectForKey:@"Rows"] isNSNull] || [aTable isEqualToString:@""] || !aTable || [tableDataInstance tableEncoding] == nil) - { - + if (!newTableName) { // Remove existing columns from the table while ([[tableContentView tableColumns] count]) { [tableContentView removeTableColumn:NSArrayObjectAtIndex([tableContentView tableColumns], 0)]; @@ -267,16 +339,20 @@ return; } - // Post a notification that a query will be performed - [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:tableDocumentInstance]; + // Otherwise, prepare to set up the new table - the table data instance already has table details set. + + // Remove existing columns from the table + while ([[tableContentView tableColumns] count]) { + [tableContentView removeTableColumn:NSArrayObjectAtIndex([tableContentView tableColumns], 0)]; + } // Retrieve the field names and types for this table from the data cache. This is used when requesting all data as part // of the fieldListForQuery method, and also to decide whether or not to preserve the current filter/sort settings. - [dataColumns addObjectsFromArray:[tableDataInstance columns]]; - columnNames = [tableDataInstance columnNames]; + [dataColumns addObjectsFromArray:[tableDetails objectForKey:@"columns"]]; + columnNames = [tableDetails objectForKey:@"columnNames"]; // Retrieve the constraints, and loop through them to add up to one foreign key to each column - NSArray *constraints = [tableDataInstance getConstraints]; + NSArray *constraints = [tableDetails objectForKey:@"constraints"]; for (NSDictionary *constraint in constraints) { @@ -297,14 +373,6 @@ NSString *nullValue = [prefs objectForKey:SPNullValue]; - // Lock drawing in the window - [tableWindow disableFlushWindow]; - - // Remove existing columns from the table - while ([[tableContentView tableColumns] count]) { - [tableContentView removeTableColumn:NSArrayObjectAtIndex([tableContentView tableColumns], 0)]; - } - // Add the new columns to the table for ( i = 0 ; i < [dataColumns count] ; i++ ) { columnDefinition = NSArrayObjectAtIndex(dataColumns, i); @@ -391,9 +459,6 @@ isDesc = NO; } - // Restore window drawing - [tableWindow enableFlushWindow]; - // Store the current first responder so filter field doesn't steal focus id currentFirstResponder = [tableWindow firstResponder]; @@ -436,7 +501,7 @@ if ([prefs boolForKey:SPLimitResults]) contentPage = pageToRestore; // Restore first responder - [tableWindow performSelectorOnMainThread:@selector(makeFirstResponder:) withObject:currentFirstResponder waitUntilDone:NO]; + [tableWindow makeFirstResponder:currentFirstResponder]; // Set the state of the table buttons [addButton setEnabled:enableInteraction]; @@ -448,37 +513,7 @@ if (!previousTableRowsCount) { [self clearTableValues]; } - - // Trigger a data refresh - [self loadTableValues]; - - // Restore the view origin if appropriate - if (!NSEqualRects(selectionViewportToRestore, NSZeroRect)) { - - // Scroll the viewport to the saved location - selectionViewportToRestore.size = [tableContentView visibleRect].size; - [tableContentView scrollRectToVisible:selectionViewportToRestore]; - } - - // Restore selection indexes if appropriate - if (selectionIndexToRestore) { - BOOL previousTableRowsSelectable = tableRowsSelectable; - tableRowsSelectable = YES; - [tableContentView selectRowIndexes:selectionIndexToRestore byExtendingSelection:NO]; - tableRowsSelectable = previousTableRowsSelectable; - } - // Update display if necessary - [tableContentView performSelectorOnMainThread:@selector(displayIfNeeded) withObject:nil waitUntilDone:NO]; - - // Init copyTable with necessary information for copying selected rows as SQL INSERT - [tableContentView setTableInstance:self withTableData:tableValues withColumns:dataColumns withTableName:selectedTable withConnection:mySQLConnection]; - - // Post the notification that the query is finished - [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:tableDocumentInstance]; - - // Clear any details to restore now that they have been restored - [self clearDetailsToRestore]; } /** @@ -950,8 +985,10 @@ // Check whether a save of the current row is required. if (![self saveRowOnDeselect]) return; - // Save view details to restore safely if possible + // Save view details to restore safely if possible (except viewport, which will be + // preserved automatically, and can then be scrolled as the table loads) [self storeCurrentDetailsForRestoration]; + [self setViewportToRestore:NSZeroRect]; // Clear the table data column cache [tableDataInstance resetColumnData]; @@ -1136,7 +1173,7 @@ - (void) updatePaginationState { NSUInteger maxPage = ceil((float)maxNumRows / [prefs floatForKey:SPLimitResultsValue]); - if (isFiltered && isLimited && tableRowsCount < [prefs integerForKey:SPLimitResultsValue]) { + if (isFiltered && !isLimited) { maxPage = contentPage; } BOOL enabledMode = ![tableDocumentInstance isWorking]; @@ -3099,6 +3136,7 @@ pthread_mutex_destroy(&tableValuesLock); [dataColumns release]; [oldRow release]; + if (selectedTable) [selectedTable release]; if (contentFilters) [contentFilters release]; if (numberOfDefaultFilters) [numberOfDefaultFilters release]; if (keys) [keys release]; |