aboutsummaryrefslogtreecommitdiffstats
path: root/Source/TableContent.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2009-12-08 01:38:13 +0000
committerrowanbeentje <rowan@beent.je>2009-12-08 01:38:13 +0000
commitc71309b319ec4ea254ed5d6efd12fd7766fc5184 (patch)
treec1fcf3e5820103064656c34282051a2add5f3efb /Source/TableContent.m
parent0483d38f13410bcf5dd81f38cf7a1c801b5f7271 (diff)
downloadsequelpro-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/TableContent.m')
-rw-r--r--Source/TableContent.m168
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];