aboutsummaryrefslogtreecommitdiffstats
path: root/Source/TableDocument.m
diff options
context:
space:
mode:
authorrowanbeentje <rowan@beent.je>2009-10-20 23:45:16 +0000
committerrowanbeentje <rowan@beent.je>2009-10-20 23:45:16 +0000
commit951330376a7b1e85dea0c44825534a4ab598c100 (patch)
tree1f098f10b4eebd660c9e2fcf1ea2926f1efbc24b /Source/TableDocument.m
parent53ca17c5bba2d57ecaee3a8ccd005fe4d6a4abe3 (diff)
downloadsequelpro-951330376a7b1e85dea0c44825534a4ab598c100.tar.gz
sequelpro-951330376a7b1e85dea0c44825534a4ab598c100.tar.bz2
sequelpro-951330376a7b1e85dea0c44825534a4ab598c100.zip
Initial work on threaded task, with an implementation of Table Content view data loading:
- Removal of AMIndeterminateProgressIndicatorCell, and addition of a custom fork of YRKSpinningProgressIndicator which fixes bugs, adds threaded drawing, and adds a determinate mode. - Addition of a task system within TableDocument, triggering display of a large central progress indicator and stopping the window from being interacted with in any way that would cause a query while the task is running. - Add threaded TableContent content fetching, including use of the new task system and determinate progress bar; make fixes to improve threading stability and interaction.
Diffstat (limited to 'Source/TableDocument.m')
-rw-r--r--Source/TableDocument.m131
1 files changed, 128 insertions, 3 deletions
diff --git a/Source/TableDocument.m b/Source/TableDocument.m
index 6b9e5eb4..cec12d09 100644
--- a/Source/TableDocument.m
+++ b/Source/TableDocument.m
@@ -51,6 +51,7 @@
#import "SPUserManager.h"
#import "SPEncodingPopupAccessory.h"
#import "SPConstants.h"
+#import "YRKSpinningProgressIndicator.h"
// Used for printing
#import "MGTemplateEngine.h"
@@ -73,6 +74,7 @@
_mainNibLoaded = NO;
_encoding = [[NSString alloc] initWithString:@"utf8"];
_isConnected = NO;
+ _isWorking = NO;
_queryMode = SP_QUERYMODE_INTERFACE;
chooseDatabaseButton = nil;
chooseDatabaseToolbarItem = nil;
@@ -92,6 +94,12 @@
spfPreferences = [[NSMutableDictionary alloc] init];
spfDocData = [[NSMutableDictionary alloc] init];
+ taskDisplayIsIndeterminate = YES;
+ taskDisplayLastValue = 0;
+ taskProgressValue = 0;
+ taskProgressValueDisplayInterval = 5;
+ taskDrawTimer = nil;
+
keyChainID = nil;
}
@@ -196,6 +204,15 @@
if (![NSBundle loadNibNamed:@"ConnectionErrorDialog" owner:self]) {
NSLog(@"Connection error dialog could not be loaded; connection failure handling will not function correctly.");
}
+ if (![NSBundle loadNibNamed:@"ProgressIndicatorLayer" owner:self]) {
+ NSLog(@"Progress indicator layer could not be loaded; progress display will not function correctly.");
+ }
+
+ // Set up the progress indicator layer - add to main window, change indicator color and size
+ [taskProgressLayer setHidden:YES];
+ [taskProgressLayer setFrame:[contentViewSplitter frame]];
+ [[tableWindow contentView] addSubview:taskProgressLayer];
+ [taskProgressIndicator setForeColor:[NSColor whiteColor]];
}
- (void)initWithConnectionFile:(NSString *)path
@@ -1174,6 +1191,111 @@
}
#pragma mark -
+#pragma mark Task progress and notification methods
+
+/**
+ * Start a document-wide task, providing a short task description for
+ * display to the user. This sets the document into working mode,
+ * preventing many actions, and shows an indeterminate progress interface
+ * to the user.
+ */
+- (void) startTaskWithDescription:(NSString *)description
+{
+
+ // Set flags and prevent further UI interaction in this window
+ _isWorking = YES;
+ [dbTablesTableView setEnabled:NO];
+ [historyControl setEnabled:NO];
+ [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskStartNotification object:[mainToolbar selectedItemIdentifier]];
+
+ // Reset the progress indicator
+ taskDisplayIsIndeterminate = YES;
+ [taskProgressIndicator setIndeterminate:YES];
+ [taskProgressIndicator animate:self];
+ [taskProgressIndicator startAnimation:self];
+ taskDisplayLastValue = 0;
+
+ // Set the descriptive label and schedule appearance in the near future
+ [taskDescriptionText setStringValue:description];
+ taskDrawTimer = [[NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(showTaskProgressLayer:) userInfo:nil repeats:NO] retain];
+}
+
+/**
+ * Show the task progress layer - after a small delay to minimise flicker.
+ */
+- (void) showTaskProgressLayer:(NSTimer *)theTimer
+{
+ [taskProgressLayer setHidden:NO];
+ [taskProgressLayer display];
+ [taskDrawTimer release], taskDrawTimer = nil;
+}
+
+/**
+ * Updates the task description shown to the user.
+ */
+- (void) setTaskDescription:(NSString *)description
+{
+ [taskDescriptionText setStringValue:description];
+}
+
+/**
+ * Sets the task percentage progress - the first call to this automatically
+ * switches the progress display to determinate.
+ */
+- (void) setTaskPercentage:(NSNumber *)taskPercentage
+{
+ taskProgressValue = [taskPercentage floatValue];
+ if (taskProgressValue > taskDisplayLastValue + taskProgressValueDisplayInterval
+ || taskProgressValue < taskDisplayLastValue - taskProgressValueDisplayInterval)
+ {
+ [taskProgressIndicator setDoubleValue:taskProgressValue];
+ taskDisplayLastValue = taskProgressValue;
+ }
+}
+
+/**
+ * Sets the task progress indicator back to indeterminate (also performed
+ * automatically whenever a new task is started)
+ */
+- (void) setTaskProgressToIndeterminate
+{
+ if (taskDisplayIsIndeterminate) return;
+ taskDisplayIsIndeterminate = YES;
+ [taskProgressIndicator setIndeterminate:YES];
+ [taskProgressIndicator startAnimation:self];
+ taskDisplayLastValue = 0;
+}
+
+/**
+ * Hide the task progress and restore the document to allow actions again.
+ */
+- (void) endTask
+{
+
+ // Cancel the draw timer if it exists
+ if (taskDrawTimer) [taskDrawTimer invalidate], [taskDrawTimer release], taskDrawTimer = nil;
+
+ // Hide the task interface
+ if (taskDisplayIsIndeterminate) [taskProgressIndicator stopAnimation:self];
+ [taskProgressLayer setHidden:YES];
+
+ // Re-enable window interface
+ _isWorking = NO;
+ [dbTablesTableView setEnabled:YES];
+ [historyControl setEnabled:YES];
+ [[NSNotificationCenter defaultCenter] postNotificationName:SPDocumentTaskEndNotification object:[mainToolbar selectedItemIdentifier]];
+}
+
+/**
+ * Returns whether the document is busy performing a task - allows UI or actions
+ * to be restricted as appropriate.
+ */
+- (BOOL) isWorking
+{
+ return _isWorking;
+}
+
+#pragma mark -
#pragma mark Encoding Methods
/**
@@ -2643,7 +2765,7 @@
*/
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
- if (!_isConnected) {
+ if (!_isConnected || _isWorking) {
return ([menuItem action] == @selector(newDocument:) || [menuItem action] == @selector(terminate:));
}
@@ -3130,7 +3252,7 @@
*/
- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem;
{
- if (!_isConnected) return NO;
+ if (!_isConnected || _isWorking) return NO;
NSString *identifier = [toolbarItem itemIdentifier];
@@ -3222,7 +3344,9 @@
*/
- (BOOL)windowShouldClose:(id)sender
{
- if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) {
+ if (_isWorking) {
+ return NO;
+ } else if ( ![tablesListInstance selectionShouldChangeInTableView:nil] ) {
return NO;
} else {
@@ -3485,6 +3609,7 @@
if (selectedDatabase) [selectedDatabase release];
if (mySQLVersion) [mySQLVersion release];
[allDatabases release];
+ if (taskDrawTimer) [taskDrawTimer release];
if(queryEditorInitString) [queryEditorInitString release];
if(spfSession) [spfSession release];
if(userManagerInstance) [userManagerInstance release];