From 951330376a7b1e85dea0c44825534a4ab598c100 Mon Sep 17 00:00:00 2001 From: rowanbeentje Date: Tue, 20 Oct 2009 23:45:16 +0000 Subject: 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. --- Interfaces/English.lproj/DBView.xib | 89 +- .../English.lproj/ProgressIndicatorLayer.xib | 1433 ++++++++++++++++++++ Source/AMIndeterminateProgressIndicatorCell.h | 57 - Source/AMIndeterminateProgressIndicatorCell.m | 189 --- Source/SPConstants.h | 2 + Source/SPConstants.m | 2 + Source/TableContent.h | 10 +- Source/TableContent.m | 199 ++- Source/TableDocument.h | 21 + Source/TableDocument.m | 131 +- Source/TablesList.h | 7 + Source/TablesList.m | 36 + Source/YRKSpinningProgressIndicator.h | 45 + Source/YRKSpinningProgressIndicator.m | 304 +++++ sequel-pro.xcodeproj/project.pbxproj | 25 +- 15 files changed, 2210 insertions(+), 340 deletions(-) create mode 100644 Interfaces/English.lproj/ProgressIndicatorLayer.xib delete mode 100644 Source/AMIndeterminateProgressIndicatorCell.h delete mode 100644 Source/AMIndeterminateProgressIndicatorCell.m create mode 100644 Source/YRKSpinningProgressIndicator.h create mode 100644 Source/YRKSpinningProgressIndicator.m diff --git a/Interfaces/English.lproj/DBView.xib b/Interfaces/English.lproj/DBView.xib index fafdfddb..54b451da 100644 --- a/Interfaces/English.lproj/DBView.xib +++ b/Interfaces/English.lproj/DBView.xib @@ -23,7 +23,8 @@ YES - + + YES @@ -2137,7 +2138,7 @@ content - + 256 YES @@ -2915,6 +2916,7 @@ {{10, 7}, {700, 544}} + Content @@ -2923,7 +2925,7 @@ customQuery - + 256 YES @@ -2950,29 +2952,6 @@ 6418 - - YES - - YES - Apple HTML pasteboard type - Apple PDF pasteboard type - Apple PICT pasteboard type - Apple PNG pasteboard type - Apple URL pasteboard type - CorePasteboardFlavorType 0x6D6F6F76 - NSColor pasteboard type - NSFilenamesPboardType - NSStringPboardType - NeXT Encapsulated PostScript v1.2 pasteboard type - NeXT RTFD pasteboard type - NeXT Rich Text Format v1.0 pasteboard type - NeXT TIFF v4.0 pasteboard type - NeXT font pasteboard type - NeXT ruler pasteboard type - WebURLsWithTitlesPboardType - public.url - - {688, 14} @@ -3795,7 +3774,6 @@ {{10, 7}, {700, 544}} - Custom Query @@ -4840,14 +4818,14 @@ - + 134217731 YES YES YES - + @@ -10803,7 +10781,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 NSResponder - + 301 YES @@ -10923,6 +10901,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 {269, 32} + NSView @@ -15168,6 +15147,38 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 6623 + + + reloadButton + + + + 6625 + + + + toolbarReloadButton + + + + 6626 + + + + toolbarActionsButton + + + + 6627 + + + + toolbarAddButton + + + + 6628 + @@ -24755,7 +24766,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 - 6623 + 6628 @@ -25493,6 +25504,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 limitRowsField limitRowsStepper multipleLineEditingButton + reloadButton removeButton secondBetweenField spHistoryControllerInstance @@ -25521,6 +25533,7 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 id id id + id SPHistoryController CMCopyTable id @@ -25690,6 +25703,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 tableTabView tableWindow tablesListInstance + taskCancelButton + taskDescriptionText + taskProgressIndicator + taskProgressLayer titleAccessoryView titleImageView titleStringView @@ -25747,6 +25764,10 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 NSTabView id id + NSButton + id + id + NSBox id id id @@ -26097,6 +26118,9 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 tableTypeButton tableWindow tablesListView + toolbarActionsButton + toolbarAddButton + toolbarReloadButton truncateTableButton truncateTableContextButton @@ -26142,6 +26166,9 @@ IGRvIHlvdSB3YW50IHRvIGFkZCBmb3IgdGhpcyBmaWVsZD8 id id id + id + id + id diff --git a/Interfaces/English.lproj/ProgressIndicatorLayer.xib b/Interfaces/English.lproj/ProgressIndicatorLayer.xib new file mode 100644 index 00000000..c63e9c95 --- /dev/null +++ b/Interfaces/English.lproj/ProgressIndicatorLayer.xib @@ -0,0 +1,1433 @@ + + + + 1050 + 10B504 + 732 + 1038.2 + 437.00 + + YES + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit + + + YES + 732 + 1.2.1 + + + + YES + + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit + + + YES + + YES + + + YES + + + + YES + + TableDocument + + + FirstResponder + + + NSApplication + + + + 301 + + YES + + + 18 + + YES + + + 256 + + YES + + + 45 + + YES + + + 256 + + YES + + + 274 + {{50, 84}, {160, 160}} + + YES + + 1 + -1 + 1 + + 3 + MAA + + + 2 + YRKSpinningProgressIndicator + + + + 290 + {{13, 34}, {234, 42}} + + YES + + 1 + -1 + 2 + + + 2 + YES + + 67239424 + 138678272 + Multiline Label + + LucidaGrande-Bold + 13 + 16 + + + + 1 + MCAwIDAAA + + + 3 + MQA + + + + + + -2147483358 + {{89, 4}, {81, 28}} + + YES + + 67239424 + 134348800 + Cancel + + LucidaGrande + 11 + 3100 + + + -2038284033 + 268435585 + + . + 200 + 25 + + + + {260, 260} + + + + {{70, 48}, {260, 260}} + + {0, 0} + + 67239424 + 0 + Box + + + 6 + System + textBackgroundColor + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 0 + 4 + 0 + NO + + 15 + + 3 + MCAwLjUAA + + + + {400, 349} + + + + {400, 349} + + {0, 0} + + 67239424 + 0 + Background + + + + 3 + MCAwLjgwMDAwMDAxMTkAA + + + + 1 + 4 + 0 + NO + + + 3 + MCAwAA + + + 1 + MSAxIDEgMAA + + + + {400, 349} + + 2 + NSView + + + + + YES + + + taskCancelButton + + + + 23 + + + + taskProgressLayer + + + + 24 + + + + taskProgressIndicator + + + + 25 + + + + taskDescriptionText + + + + 33 + + + + + YES + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + 19 + + + YES + + + + + + 10 + + + YES + + + + + + + + 17 + + + YES + + + + + + 15 + + + YES + + + + + + 11 + + + YES + + + + + 16 + + + + + 18 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBAttributePlaceholdersKey + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBEditorWindowLastContentRect + 1.IBPluginDependency + 1.WindowOrigin + 1.editorWindowContentRectSynchronizationRect + 10.IBPluginDependency + 11.IBPluginDependency + 11.IBViewIntegration.shadowBlurRadius + 11.IBViewIntegration.shadowColor + 11.IBViewIntegration.shadowOffsetHeight + 11.IBViewIntegration.shadowOffsetWidth + 15.IBPluginDependency + 15.IBViewIntegration.shadowBlurRadius + 15.IBViewIntegration.shadowOffsetHeight + 15.IBViewIntegration.shadowOffsetWidth + 16.IBPluginDependency + 17.IBPluginDependency + 18.IBPluginDependency + 19.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + + YES + + + YES + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{309, 442}, {400, 349}} + com.apple.InterfaceBuilder.CocoaPlugin + {628, 654} + {{357, 416}, {480, 272}} + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.brandonwalkin.BWToolkit + com.brandonwalkin.BWToolkit + com.apple.InterfaceBuilder.CocoaPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 33 + + + + YES + + NSObject + + IBProjectSource + Frameworks/MCPKit/MCPFoundationKit/MCPConnection.h + + + + NSObject + + IBProjectSource + Frameworks/MCPKit/MCPFoundationKit/MCPNull.h + + + + NSObject + + IBProjectSource + Source/CMImageView.h + + + + NSObject + + IBProjectSource + Source/SPConnectionController.h + + + + NSObject + + IBProjectSource + Source/SPContentFilterManager.h + + + + NSObject + + IBProjectSource + Source/SPNotLoaded.h + + + + NSObject + + IBProjectSource + Source/SPQueryFavoriteManager.h + + + + NSObject + + toggleCollapse: + id + + + IBProjectSource + Source/TablesList.h + + + + NSTextView + + YES + + YES + doDecomposedStringWithCanonicalMapping: + doDecomposedStringWithCompatibilityMapping: + doPrecomposedStringWithCanonicalMapping: + doPrecomposedStringWithCompatibilityMapping: + doRemoveDiacritics: + doSelectionLowerCase: + doSelectionTitleCase: + doSelectionUpperCase: + doTranspose: + insertNULLvalue: + selectCurrentLine: + selectCurrentWord: + selectEnclosingBrackets: + + + YES + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + IBProjectSource + Source/SPTextViewAdditions.h + + + + NSWindow + + IBProjectSource + Source/SPWindowAdditions.h + + + + TableDocument + NSDocument + + YES + + YES + addConnectionToFavorites: + addDatabase: + analyzeTable: + backForwardInHistory: + checkTable: + checksumTable: + chooseDatabase: + chooseEncoding: + closeDatabaseSheet: + closeErrorConnectionSheet: + closePanelSheet: + closePasswordSheet: + closeSheet: + copy: + copyCreateTableSyntax: + copyCreateTableSyntaxFromSheet: + copyServerVariableName: + copyServerVariableValue: + export: + exportMultipleTables: + exportTable: + flushPrivileges: + flushTable: + import: + openCurrentConnectionInNewWindow: + optimizeTable: + removeDatabase: + repairTable: + saveConnectionSheet: + saveCreateSyntax: + saveServerVariables: + setDatabases: + showCreateTableSyntax: + showMySQLHelp: + showUserManager: + showVariables: + validateSaveConnectionAccessory: + viewContent: + viewQuery: + viewRelations: + viewStatus: + viewStructure: + + + YES + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + id + + + + YES + + YES + addDatabaseButton + chooseDatabaseButton + connectionErrorDialog + contentViewSplitter + createTableSyntaxTextField + createTableSyntaxTextView + createTableSyntaxWindow + customQueryInstance + customQueryTextView + databaseDataInstance + databaseEncodingButton + databaseNameField + databaseSheet + dbTablesTableView + encodingPopUp + exportControllerInstance + extendedTableInfoInstance + favoritesButton + historyControl + inputTextWindow + inputTextWindowHeader + inputTextWindowMessage + inputTextWindowSecureTextField + listFilterField + queryProgressBar + saveConnectionAccessory + saveConnectionAutoConnect + saveConnectionEncrypt + saveConnectionEncryptString + saveConnectionIncludeData + saveConnectionIncludeQuery + saveConnectionSavePassword + saveConnectionSavePasswordAlert + saveVariablesButton + sidebarGrabber + spHistoryControllerInstance + tableContentInstance + tableDataInstance + tableDumpInstance + tableInfoCollapseButton + tableInfoTable + tableListSplitter + tableRelationsInstance + tableSourceInstance + tableTabView + tableWindow + tablesListInstance + taskCancelButton + taskDescriptionText + taskProgressIndicator + taskProgressLayer + titleAccessoryView + titleImageView + titleStringView + variablesCountTextField + variablesSearchField + variablesSheet + variablesTableView + + + YES + id + id + NSWindow + NSSplitView + NSTextField + NSTextView + NSWindow + id + NSTextView + id + id + id + id + NSTableView + NSPopUpButton + id + id + id + id + id + id + id + id + NSSearchField + id + id + id + id + NSSecureTextField + id + id + id + id + NSButton + id + id + id + id + id + NSButton + NSTableView + NSSplitView + id + id + NSTabView + id + id + NSButton + id + id + NSBox + id + id + id + NSTextField + NSSearchField + id + id + + + + IBProjectSource + Source/TableDocument.h + + + + YRKSpinningProgressIndicator + NSView + + YES + + YES + animate: + startAnimation: + stopAnimation: + + + YES + id + id + id + + + + IBProjectSource + Source/YRKSpinningProgressIndicator.h + + + + + YES + + NSActionCell + NSCell + + IBFrameworkSource + AppKit.framework/Headers/NSActionCell.h + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSApplicationScripting.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSColorPanel.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSHelpManager.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSPageLayout.h + + + + NSApplication + + IBFrameworkSource + AppKit.framework/Headers/NSUserInterfaceItemSearching.h + + + + NSBox + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSBox.h + + + + NSButton + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSButton.h + + + + NSButtonCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSButtonCell.h + + + + NSCell + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSCell.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + YES + + YES + printDocument: + revertDocumentToSaved: + runPageLayout: + saveDocument: + saveDocumentAs: + saveDocumentTo: + + + YES + id + id + id + id + id + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocument + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentScripting.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSAccessibility.h + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDictionaryController.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSDragging.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontManager.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSFontPanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSKeyValueBinding.h + + + + NSObject + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSNibLoading.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSOutlineView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSPasteboard.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSSavePanel.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSToolbarItem.h + + + + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObjectScripting.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPortCoder.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptClassDescription.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptObjectSpecifiers.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSScriptWhoseTests.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLDownload.h + + + + NSObject + + IBFrameworkSource + Growl.framework/Headers/GrowlApplicationBridge.h + + + + NSObject + + IBFrameworkSource + Sparkle.framework/Headers/SUAppcast.h + + + + NSObject + + IBFrameworkSource + Sparkle.framework/Headers/SUUpdater.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebDownload.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebEditingDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebFrameLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebJavaPlugIn.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPlugin.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPluginContainer.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebPolicyDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebResourceLoadDelegate.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebScriptObject.h + + + + NSObject + + IBFrameworkSource + WebKit.framework/Headers/WebUIDelegate.h + + + + NSPopUpButton + NSButton + + IBFrameworkSource + AppKit.framework/Headers/NSPopUpButton.h + + + + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSInterfaceStyle.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSSearchField + NSTextField + + IBFrameworkSource + AppKit.framework/Headers/NSSearchField.h + + + + NSSecureTextField + NSTextField + + IBFrameworkSource + AppKit.framework/Headers/NSSecureTextField.h + + + + NSSplitView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSSplitView.h + + + + NSTabView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSTabView.h + + + + NSTableView + NSControl + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextField + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTextField.h + + + + NSTextFieldCell + NSActionCell + + IBFrameworkSource + AppKit.framework/Headers/NSTextFieldCell.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSClipView.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSRulerView.h + + + + NSView + NSResponder + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSDrawer.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + NSWindow + + IBFrameworkSource + AppKit.framework/Headers/NSWindowScripting.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaPlugin.macosx + + + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + ../../sequel-pro.xcodeproj + 3 + + diff --git a/Source/AMIndeterminateProgressIndicatorCell.h b/Source/AMIndeterminateProgressIndicatorCell.h deleted file mode 100644 index 04f7f13b..00000000 --- a/Source/AMIndeterminateProgressIndicatorCell.h +++ /dev/null @@ -1,57 +0,0 @@ -// -// $Id$ -// -// AMIndeterminateProgressIndicatorCell.h -// sequel-pro -// -// Created by Andreas Mayer on January 23, 2007 -// Copyright 2007 Andreas Mayer (andreas@harmless.de). All rights reserved. -// -// License: http://www.opensource.org/licenses/bsd-license.php -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// More info at - -#import - -@interface AMIndeterminateProgressIndicatorCell : NSCell { - double doubleValue; - NSTimeInterval animationDelay; - BOOL displayedWhenStopped; - BOOL spinning; - NSColor *color; - float redComponent; - float greenComponent; - float blueComponent; -} - -- (NSColor *)color; -- (void)setColor:(NSColor *)value; - -- (double)doubleValue; -- (void)setDoubleValue:(double)value; - -- (NSTimeInterval)animationDelay; -- (void)setAnimationDelay:(NSTimeInterval)value; - -- (BOOL)isDisplayedWhenStopped; -- (void)setDisplayedWhenStopped:(BOOL)value; - -- (BOOL)isSpinning; -- (void)setSpinning:(BOOL)value; - - -@end diff --git a/Source/AMIndeterminateProgressIndicatorCell.m b/Source/AMIndeterminateProgressIndicatorCell.m deleted file mode 100644 index 66fe1a39..00000000 --- a/Source/AMIndeterminateProgressIndicatorCell.m +++ /dev/null @@ -1,189 +0,0 @@ -// -// $Id$ -// -// AMIndeterminateProgressIndicatorCell.m -// sequel-pro -// -// Created by Andreas Mayer on January 23, 2007 -// Copyright 2007 Andreas Mayer (andreas@harmless.de). All rights reserved. -// -// License: http://www.opensource.org/licenses/bsd-license.php -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// More info at - -#import "AMIndeterminateProgressIndicatorCell.h" - -#define ConvertAngle(a) (fmod((90.0-(a)), 360.0)) - -#define DEG2RAD 0.017453292519943295 - -@implementation AMIndeterminateProgressIndicatorCell - -- (id)init -{ - if (self = [super initImageCell:nil]) { - [self setAnimationDelay:5.0/60.0]; - [self setDisplayedWhenStopped:YES]; - [self setDoubleValue:0.0]; - [self setColor:[NSColor blackColor]]; - } - return self; -} - -- (void)dealloc -{ - [NSColor release]; - [super dealloc]; -} - -- (NSColor *)color -{ - return [[color retain] autorelease]; -} - -- (void)setColor:(NSColor *)value -{ - float alphaComponent; - if (color != value) { - [color release]; - color = [value retain]; - [[color colorUsingColorSpaceName:@"NSCalibratedRGBColorSpace"] getRed:&redComponent green:&greenComponent blue:&blueComponent alpha:&alphaComponent]; - NSAssert((alphaComponent > 0.999), @"color must be opaque"); - } -} - -- (double)doubleValue -{ - return doubleValue; -} - -- (void)setDoubleValue:(double)value -{ - if (doubleValue != value) { - doubleValue = value; - if (doubleValue > 1.0) { - doubleValue = 1.0; - } else if (doubleValue < 0.0) { - doubleValue = 0.0; - } - } -} - -- (NSTimeInterval)animationDelay -{ - return animationDelay; -} - -- (void)setAnimationDelay:(NSTimeInterval)value -{ - if (animationDelay != value) { - animationDelay = value; - } -} - -- (BOOL)isDisplayedWhenStopped -{ - return displayedWhenStopped; -} - -- (void)setDisplayedWhenStopped:(BOOL)value -{ - if (displayedWhenStopped != value) { - displayedWhenStopped = value; - } -} - -- (BOOL)isSpinning -{ - return spinning; -} - -- (void)setSpinning:(BOOL)value -{ - if (spinning != value) { - spinning = value; - } -} - -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - // cell has no border - [self drawInteriorWithFrame:cellFrame inView:controlView]; -} - -- (void)drawInteriorWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - //NSLog(@"cellFrame: %f %f %f %f", cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height); - if ([self isSpinning] || [self isDisplayedWhenStopped]) { - float flipFactor = ([controlView isFlipped] ? 1.0 : -1.0); - int step = round([self doubleValue]/(5.0/60.0)); - float cellSize = MIN(cellFrame.size.width, cellFrame.size.height); - NSPoint center = cellFrame.origin; - center.x += cellSize/2.0; - center.y += cellFrame.size.height/2.0; - float outerRadius; - float innerRadius; - float strokeWidth = cellSize*0.08; - if (cellSize >= 32.0) { - outerRadius = cellSize*0.38; - innerRadius = cellSize*0.23; - } else { - outerRadius = cellSize*0.48; - innerRadius = cellSize*0.27; - } - float a; // angle - NSPoint inner; - NSPoint outer; - // remember defaults - NSLineCapStyle previousLineCapStyle = [NSBezierPath defaultLineCapStyle]; - float previousLineWidth = [NSBezierPath defaultLineWidth]; - // new defaults for our loop - [NSBezierPath setDefaultLineCapStyle:NSRoundLineCapStyle]; - [NSBezierPath setDefaultLineWidth:strokeWidth]; - if ([self isSpinning]) { - a = (270+(step* 30))*DEG2RAD; - } else { - a = 270*DEG2RAD; - } - a = flipFactor*a; - int i; - for (i = 0; i < 12; i++) { -// [[NSColor colorWithCalibratedWhite:MIN(sqrt(i)*0.25, 0.8) alpha:1.0] set]; -// [[NSColor colorWithCalibratedWhite:0.0 alpha:1.0-sqrt(i)*0.25] set]; - [[NSColor colorWithCalibratedRed:redComponent green:greenComponent blue:blueComponent alpha:1.0-sqrt(i)*0.25] set]; - outer = NSMakePoint(center.x+cos(a)*outerRadius, center.y+sin(a)*outerRadius); - inner = NSMakePoint(center.x+cos(a)*innerRadius, center.y+sin(a)*innerRadius); - [NSBezierPath strokeLineFromPoint:inner toPoint:outer]; - a -= flipFactor*30*DEG2RAD; - } - // restore previous defaults - [NSBezierPath setDefaultLineCapStyle:previousLineCapStyle]; - [NSBezierPath setDefaultLineWidth:previousLineWidth]; - } -} - -- (void)setObjectValue:(id)value -{ - if ([value respondsToSelector:@selector(boolValue)]) { - [self setSpinning:[value boolValue]]; - } else { - [self setSpinning:NO]; - } -} - - -@end diff --git a/Source/SPConstants.h b/Source/SPConstants.h index 9e257894..420d1823 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -109,3 +109,5 @@ extern NSString *SPQueryFavorites; extern NSString *SPFavorites; extern NSString *SPTableColumnWidths; extern NSString *SPQueryHistory; +extern NSString *SPDocumentTaskStartNotification; +extern NSString *SPDocumentTaskEndNotification; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index b2a88ee1..91ae17b1 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -92,3 +92,5 @@ NSString *SPQueryFavorites = @"queryFavorites"; NSString *SPFavorites = @"favorites"; NSString *SPTableColumnWidths = @"tableColumnWidths"; NSString *SPQueryHistory = @"queryHistory"; +NSString *SPDocumentTaskStartNotification = @"DocumentTaskStarted"; +NSString *SPDocumentTaskEndNotification = @"DocumentTaskEnded"; diff --git a/Source/TableContent.h b/Source/TableContent.h index 6ecc3a8e..09c50a0e 100644 --- a/Source/TableContent.h +++ b/Source/TableContent.h @@ -47,6 +47,7 @@ IBOutlet id addButton; IBOutlet id copyButton; IBOutlet id removeButton; + IBOutlet id reloadButton; IBOutlet id multipleLineEditingButton; IBOutlet id countText; IBOutlet id limitRowsField; @@ -60,6 +61,7 @@ NSString *selectedTable, *usedQuery; NSMutableArray *tableValues, *dataColumns, *keys, *oldRow; + NSUInteger tableValuesCount; NSString *compareType; NSNumber *sortCol; BOOL isEditingRow, isEditingNewRow, isSavingRow, isDesc, setLimit; @@ -82,7 +84,8 @@ // Table loading methods and information - (void) loadTable:(NSString *)aTable; -- (void) loadTableValues; +- (void) loadTableValuesWithCallback:(SEL)tableContentCallbackMethod; +- (void) loadTableValuesTaskWithCallback:(id)encodedTableContentCallbackMethod; - (NSString *) tableFilterString; - (void) updateCountText; @@ -102,6 +105,10 @@ - (NSArray *)currentResult; - (NSArray *)currentDataResult; +// Task interaction +- (void) startDocumentTaskForTab:(NSNotification *)aNotification; +- (void) endDocumentTaskForTab:(NSNotification *)aNotification; + // Additional methods - (void)setConnection:(MCPConnection *)theConnection; - (void)clickLinkArrow:(SPTextAndLinkCell *)theArrowCell; @@ -113,6 +120,7 @@ - (BOOL)tableContainsBlobOrTextColumns; - (NSString *)fieldListForQuery; - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)contextInfo; +- (void)finalizeRowDeletion; - (void)updateNumberOfRows; - (int)fetchNumberOfRows; - (BOOL)saveRowOnDeselect; diff --git a/Source/TableContent.m b/Source/TableContent.m index d21c8df5..36eaa2e2 100644 --- a/Source/TableContent.m +++ b/Source/TableContent.m @@ -59,6 +59,7 @@ if ((self == [super init])) { tableValues = [[NSMutableArray alloc] init]; + tableValuesCount = 0; dataColumns = [[NSMutableArray alloc] init]; oldRow = [[NSMutableArray alloc] init]; @@ -119,6 +120,16 @@ { // Set the table content view's vertical gridlines if required [tableContentView setGridStyleMask:([prefs boolForKey:SPDisplayTableViewVerticalGridlines]) ? NSTableViewSolidVerticalGridLineMask : NSTableViewGridNone]; + + // Add observers for document task activity + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(startDocumentTaskForTab:) + name:SPDocumentTaskStartNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(endDocumentTaskForTab:) + name:SPDocumentTaskEndNotification + object:nil]; } #pragma mark - @@ -164,6 +175,7 @@ if ( [[[tableDataInstance statusValues] objectForKey:@"Rows"] isNSNull] || [aTable isEqualToString:@""] || !aTable || [tableDataInstance tableEncoding] == nil) { // Empty the stored data arrays + tableValuesCount = 0; [tableValues removeAllObjects]; [tableContentView reloadData]; isFiltered = NO; @@ -394,8 +406,15 @@ [removeButton setEnabled:NO]; // Trigger a data refresh - [self loadTableValues]; + [self loadTableValuesWithCallback:@selector(finalizeTableLoad)]; +} +/** + * Callback to finish setting up a freshly loaded table once + * the values are available. + */ +- (void) finalizeTableLoad +{ // Restore the view origin if appropriate if (!NSEqualRects(selectionViewportToRestore, NSZeroRect)) { @@ -430,17 +449,36 @@ * using filters and limits as appropriate. * Will not refresh the table view itself. */ -- (void) loadTableValues +- (void) loadTableValuesWithCallback:(SEL)tableContentCallbackMethod +{ + if (!selectedTable) return; + + [tableDocumentInstance startTaskWithDescription:[NSString stringWithFormat:NSLocalizedString(@"Loading %@...", @"Loading table string"), selectedTable]]; + + NSValue *encodedCallbackMethod = nil; + if (tableContentCallbackMethod) + encodedCallbackMethod = [NSValue valueWithBytes:&tableContentCallbackMethod objCType:@encode(SEL)]; + [NSThread detachNewThreadSelector:@selector(loadTableValuesTaskWithCallback:) toTarget:self withObject:encodedCallbackMethod]; +} + +- (void) loadTableValuesTaskWithCallback:(id)encodedTableContentCallbackMethod { // If no table is selected, return - if(!selectedTable) return; + if (!selectedTable) return; + NSAutoreleasePool *tableLoadPool = [[NSAutoreleasePool alloc] init]; NSMutableString *queryString; NSString *queryStringBeforeLimit = nil; NSString *filterString; MCPStreamingResult *streamingResult; + SEL callbackMethod = NULL; int rowsToLoad = [[tableDataInstance statusValueForKey:@"Rows"] intValue]; - + + // Remove all items from the table + tableValuesCount = 0; + [tableContentView performSelectorOnMainThread:@selector(noteNumberOfRowsChanged) withObject:nil waitUntilDone:YES]; + [tableValues removeAllObjects]; + // Notify any listeners that a query has started [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryWillBePerformed" object:self]; @@ -492,7 +530,7 @@ [streamingResult release]; // If the result is empty, and a limit is active, reset the limit - if ([prefs boolForKey:SPLimitResults] && queryStringBeforeLimit && ![tableValues count]) { + if ([prefs boolForKey:SPLimitResults] && queryStringBeforeLimit && !tableValuesCount) { [limitRowsField setStringValue:@"1"]; queryString = [NSMutableString stringWithFormat:@"%@ LIMIT 0,%d", queryStringBeforeLimit, [prefs integerForKey:SPLimitResultsValue]]; [self setUsedQuery:queryString]; @@ -503,7 +541,7 @@ if ([prefs boolForKey:SPLimitResults] && ([limitRowsField intValue] > 1 - || [tableValues count] == [prefs integerForKey:SPLimitResultsValue])) + || tableValuesCount == [prefs integerForKey:SPLimitResultsValue])) { isLimited = YES; } else { @@ -518,6 +556,17 @@ // Notify listenters that the query has finished [[NSNotificationCenter defaultCenter] postNotificationName:@"SMySQLQueryHasBeenPerformed" object:self]; + + // Set up the callback if present + if (encodedTableContentCallbackMethod) { + [encodedTableContentCallbackMethod getValue:&callbackMethod]; + [self performSelectorOnMainThread:callbackMethod withObject:nil waitUntilDone:NO]; + } else { + [tableContentView reloadData]; + } + + [tableDocumentInstance endTask]; + [tableLoadPool release]; } /** @@ -683,25 +732,25 @@ // If no filter or limit is active, show just the count of rows in the table if (!isFiltered && !isLimited) { - if ([tableValues count] == 1) - [countString appendFormat:NSLocalizedString(@"%d row in table", @"text showing a single row in the result"), [tableValues count]]; + if (tableValuesCount == 1) + [countString appendFormat:NSLocalizedString(@"%d row in table", @"text showing a single row in the result"), tableValuesCount]; else - [countString appendFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), [tableValues count]]; + [countString appendFormat:NSLocalizedString(@"%d rows in table", @"text showing how many rows are in the result"), tableValuesCount]; // If a limit is active, display a string suggesting a limit is active } else if (!isFiltered && isLimited) { - [countString appendFormat:NSLocalizedString(@"Rows %d-%d of %@%d from table", @"text showing how many rows are in the limited result"), [limitRowsField intValue], [limitRowsField intValue]+[tableValues count]-1, maxNumRowsIsEstimate?@"~":@"", maxNumRows]; + [countString appendFormat:NSLocalizedString(@"Rows %d-%d of %@%d from table", @"text showing how many rows are in the limited result"), [limitRowsField intValue], [limitRowsField intValue]+tableValuesCount-1, maxNumRowsIsEstimate?@"~":@"", maxNumRows]; // If just a filter is active, show a count and an indication a filter is active } else if (isFiltered && !isLimited) { - if ([tableValues count] == 1) - [countString appendFormat:NSLocalizedString(@"%d row of %@%d matches filter", @"text showing how a single rows matched filter"), [tableValues count], maxNumRowsIsEstimate?@"~":@"", maxNumRows]; + if (tableValuesCount == 1) + [countString appendFormat:NSLocalizedString(@"%d row of %@%d matches filter", @"text showing how a single rows matched filter"), tableValuesCount, maxNumRowsIsEstimate?@"~":@"", maxNumRows]; else - [countString appendFormat:NSLocalizedString(@"%d rows of %@%d match filter", @"text showing how many rows matched filter"), [tableValues count], maxNumRowsIsEstimate?@"~":@"", maxNumRows]; + [countString appendFormat:NSLocalizedString(@"%d rows of %@%d match filter", @"text showing how many rows matched filter"), tableValuesCount, maxNumRowsIsEstimate?@"~":@"", maxNumRows]; // If both a filter and limit is active, display full string } else { - [countString appendFormat:NSLocalizedString(@"Rows %d-%d from filtered matches", @"text showing how many rows are in the limited filter match"), [limitRowsField intValue], [limitRowsField intValue]+[tableValues count]-1]; + [countString appendFormat:NSLocalizedString(@"Rows %d-%d from filtered matches", @"text showing how many rows are in the limited filter match"), [limitRowsField intValue], [limitRowsField intValue]+tableValuesCount-1]; } // If rows are selected, append selection count @@ -743,6 +792,7 @@ */ - (IBAction)filterTable:(id)sender { + if ([tableDocumentInstance isWorking]) return; // Check whether a save of the current row is required. if (![self saveRowOnDeselect]) return; @@ -762,11 +812,8 @@ } // Reload data using the new filter settings - [self loadTableValues]; - - // Reset the table view [tableContentView scrollPoint:NSMakePoint(0.0, 0.0)]; - [tableContentView reloadData]; + [self loadTableValuesWithCallback:NULL]; } /** @@ -858,6 +905,7 @@ } } [tableValues addObject:newRow]; + tableValuesCount++; [tableContentView reloadData]; [tableContentView selectRowIndexes:[NSIndexSet indexSetWithIndex:[tableContentView numberOfRows]-1] byExtendingSelection:NO]; @@ -1096,6 +1144,8 @@ */ - (void)clickLinkArrow:(SPTextAndLinkCell *)theArrowCell { + if ([tableDocumentInstance isWorking]) return; + if ([theArrowCell getClickedColumn] == NSNotFound || [theArrowCell getClickedRow] == NSNotFound) return; int dataColumnIndex = [[[[tableContentView tableColumns] objectAtIndex:[theArrowCell getClickedColumn]] identifier] intValue]; @@ -1318,11 +1368,8 @@ NSMutableArray *columnBlobStatuses = [[NSMutableArray alloc] init]; NSUInteger i; - // Update the progress wheel every ~15% - NSUInteger loadingIndicatorDelta = 15; - - NSUInteger lastProgressValue = loadingIndicatorDelta; float relativeTargetRowCount = 100.0/targetRowCount; + NSUInteger nextTableDisplayBoundary = 50; long rowsProcessed = 0; long columnsCount = [dataColumns count]; @@ -1336,12 +1383,6 @@ [columnBlobStatuses addObject:[NSNumber numberWithBool:[tableDataInstance columnIsBlobOrText:[NSArrayObjectAtIndex(dataColumns, i) objectForKey:@"name"] ]]]; } - // Remove all items from the table and reset the progress indicator - [tableValues removeAllObjects]; - if (targetRowCount) [dataLoadingIndicator setIndeterminate:NO]; - [dataLoadingIndicator setDoubleValue:(int)loadingIndicatorDelta/2]; - [dataLoadingIndicator display]; - // Set up an autorelease pool for row processing dataLoadingPool = [[NSAutoreleasePool alloc] init]; @@ -1351,6 +1392,7 @@ // Add values for hidden blob and text fields if appropriate if ( prefsLoadBlobsAsNeeded ) { NSMutableArrayAddObject(tableValues, [NSMutableArray arrayWithCapacity:columnsCount]); + tableValuesCount++; newRow = NSArrayObjectAtIndex(tableValues, rowsProcessed); for ( i = 0 ; i < columnsCount ; i++ ) { if ( [NSArrayObjectAtIndex(columnBlobStatuses, i) boolValue] ) { @@ -1363,18 +1405,22 @@ // Otherwise just add the new row } else { NSMutableArrayAddObject(tableValues, [NSMutableArray arrayWithArray:tempRow]); + tableValuesCount++; } - // Update the progress bar as necessary, minimising updates + // Update the task interface as necessary rowsProcessed++; - if (rowsProcessed < targetRowCount) { - [dataLoadingIndicator setDoubleValue:(rowsProcessed*relativeTargetRowCount)]; - if ((int)[dataLoadingIndicator doubleValue] > lastProgressValue) { - [dataLoadingIndicator display]; - lastProgressValue = (int)[dataLoadingIndicator doubleValue] + loadingIndicatorDelta; + if (!isFiltered) { + if (rowsProcessed < targetRowCount) { + [tableDocumentInstance performSelectorOnMainThread:@selector(setTaskPercentage:) withObject:[NSNumber numberWithFloat:(rowsProcessed*relativeTargetRowCount)] waitUntilDone:NO]; + } else if (rowsProcessed == targetRowCount) { + [tableDocumentInstance performSelectorOnMainThread:@selector(setTaskProgressToIndeterminate) withObject:nil waitUntilDone:NO]; + } + + if (rowsProcessed > nextTableDisplayBoundary) { + [tableContentView reloadData]; + nextTableDisplayBoundary *= 3; } - } else if (rowsProcessed == targetRowCount) { - [dataLoadingIndicator setIndeterminate:YES]; } // Drain and reset the autorelease pool every ~1024 rows @@ -1520,9 +1566,8 @@ // New row created successfully if ( isEditingNewRow ) { if ( [prefs boolForKey:SPReloadAfterAddingRow] ) { - [self loadTableValues]; [tableWindow endEditingFor:nil]; - [tableContentView reloadData]; + [self loadTableValuesWithCallback:NULL]; } else { // Set the insertId for fields with auto_increment @@ -1539,9 +1584,8 @@ // Reload table if set to - otherwise no action required. if ( [prefs boolForKey:SPReloadAfterEditingRow] ) { - [self loadTableValues]; [tableWindow endEditingFor:nil]; - [tableContentView reloadData]; + [self loadTableValuesWithCallback:NULL]; } } currentlyEditingRow = -1; @@ -1749,6 +1793,7 @@ withObject:[NSMutableArray arrayWithArray:oldRow]]; isEditingRow = NO; } else { + tableValuesCount--; [tableValues removeObjectAtIndex:[tableContentView selectedRow]]; isEditingRow = NO; isEditingNewRow = NO; @@ -1963,20 +2008,25 @@ // Refresh table content if ( errors || reloadAfterRemovingRow ) { - [self loadTableValues]; - [tableContentView reloadData]; + [self loadTableValuesWithCallback:@selector(finalizeRowDeletion)]; } else { - for ( i = 0 ; i < [tableValues count] ; i++ ) { + for ( i = 0 ; i < tableValuesCount ; i++ ) { if ( ![selectedRows containsIndex:i] ) [tempResult addObject:NSArrayObjectAtIndex(tableValues, i)]; } + tableValuesCount = [tempResult count]; [tableValues setArray:tempResult]; + [tableContentView deselectAll:self]; [tableContentView reloadData]; } - [tableContentView deselectAll:self]; } } } +- (void) finalizeRowDeletion +{ + [tableContentView deselectAll:self]; + [tableContentView reloadData]; +} /** * Show Error sheet (can be called from inside of a endSheet selector) @@ -2176,7 +2226,7 @@ // For unfiltered and non-limited tables, use the result count - and update the status count if (!isLimited && !isFiltered) { - maxNumRows = [tableValues count]; + maxNumRows = tableValuesCount; maxNumRowsIsEstimate = NO; [tableDataInstance setStatusValue:[NSString stringWithFormat:@"%d", maxNumRows] forKey:@"Rows"]; [tableDataInstance setStatusValue:@"y" forKey:@"RowsCountAccurate"]; @@ -2209,7 +2259,7 @@ if (checkStatusCount) { NSInteger foundMaxRows; if ([prefs boolForKey:SPLimitResults]) { - foundMaxRows = [limitRowsField intValue] - 1 + [tableValues count]; + foundMaxRows = [limitRowsField intValue] - 1 + tableValuesCount; if (foundMaxRows > maxNumRows) { if (foundMaxRows == [limitRowsField intValue] - 1 + [prefs integerForKey:SPLimitResultsValue]) { maxNumRows = foundMaxRows + 1; @@ -2219,8 +2269,8 @@ maxNumRowsIsEstimate = NO; } } - } else if ([tableValues count] > maxNumRows) { - maxNumRows = [tableValues count]; + } else if (tableValuesCount > maxNumRows) { + maxNumRows = tableValuesCount; maxNumRowsIsEstimate = YES; } [tableDataInstance setStatusValue:[NSString stringWithFormat:@"%d", maxNumRows] forKey:@"Rows"]; @@ -2284,11 +2334,13 @@ - (int)numberOfRowsInTableView:(NSTableView *)aTableView { - return [tableValues count]; + return tableValuesCount; } - (id)tableView:(CMCopyTable *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex { + if (rowIndex >= tableValuesCount) return nil; + id theValue = NSArrayObjectAtIndex(NSArrayObjectAtIndex(tableValues, rowIndex), [[aTableColumn identifier] intValue]); if ([theValue isKindOfClass:[NSData class]]) @@ -2309,6 +2361,7 @@ - (void)tableView:(CMCopyTable *)aTableView willDisplayCell:(id)cell forTableColumn:(NSTableColumn*)aTableColumn row:(int)row { + if (row >= tableValuesCount) return; if (![cell respondsToSelector:@selector(setTextColor:)]) return; // If user wants to edit 'cell' set text color to black and return to avoid @@ -2384,9 +2437,6 @@ if (sortCol) [sortCol release]; sortCol = [[NSNumber alloc] initWithInt:[[tableColumn identifier] intValue]]; - // Update data using the new sort order - [self loadTableValues]; - if ( ![[mySQLConnection getLastErrorMessage] isEqualToString:@""] ) { NSBeginAlertSheet(NSLocalizedString(@"Error", @"error"), NSLocalizedString(@"OK", @"OK button"), nil, nil, tableWindow, self, nil, nil, nil, [NSString stringWithFormat:NSLocalizedString(@"Couldn't sort table. MySQL said: %@", @"message of panel when sorting of table failed"), [mySQLConnection getLastErrorMessage]]); @@ -2401,7 +2451,8 @@ [tableContentView setIndicatorImage:[NSImage imageNamed:@"NSAscendingSortIndicator"] inTableColumn:tableColumn]; } - [tableContentView reloadData]; + // Update data using the new sort order + [self loadTableValuesWithCallback:NULL]; } - (void)tableViewSelectionDidChange:(NSNotification *)aNotification @@ -2587,6 +2638,46 @@ return (proposedMin + 200); } +#pragma mark - +#pragma mark Task interaction + +/** + * Disable all content interactive elements during an ongoing task. + */ +- (void) startDocumentTaskForTab:(NSNotification *)aNotification +{ + + // Only disable elements if the current tab is the content view + if (![[aNotification object] isEqualToString:@"SwitchToTableContentToolbarItemIdentifier"]) return; + + [tableContentView setEnabled:NO]; + [addButton setEnabled:NO]; + [removeButton setEnabled:NO]; + [copyButton setEnabled:NO]; + [reloadButton setEnabled:NO]; + [filterButton setEnabled:NO]; +} + +/** + * Enable all content interactive elements after an ongoing task. + */ +- (void) endDocumentTaskForTab:(NSNotification *)aNotification +{ + + // Only enable elements if the current tab is the content view + if (![[aNotification object] isEqualToString:@"SwitchToTableContentToolbarItemIdentifier"]) return; + + [tableContentView setEnabled:YES]; + if ( ![[[tableDataInstance statusValues] objectForKey:@"Rows"] isNSNull] && selectedTable && [selectedTable length] && [tableDataInstance tableEncoding]) [addButton setEnabled:YES]; + if ([tableContentView numberOfSelectedRows] > 0) { + [removeButton setEnabled:YES]; + [copyButton setEnabled:YES]; + } + [reloadButton setEnabled:YES]; + [filterButton setEnabled:[fieldField isEnabled]]; + [tableContentView setNeedsDisplay:YES]; +} + #pragma mark - #pragma mark Other methods @@ -2692,6 +2783,8 @@ // Last but not least - (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [tableValues release]; [dataColumns release]; [oldRow release]; diff --git a/Source/TableDocument.h b/Source/TableDocument.h index 465d49b7..6720527a 100644 --- a/Source/TableDocument.h +++ b/Source/TableDocument.h @@ -68,6 +68,11 @@ enum sp_current_query_mode IBOutlet id variablesSheet; IBOutlet id queryProgressBar; + IBOutlet NSBox *taskProgressLayer; + IBOutlet id taskProgressIndicator; + IBOutlet id taskDescriptionText; + IBOutlet NSButton *taskCancelButton; + IBOutlet id favoritesButton; IBOutlet id databaseNameField; @@ -129,9 +134,16 @@ enum sp_current_query_mode BOOL _encodingViaLatin1; BOOL _shouldOpenConnectionAutomatically; BOOL _isConnected; + BOOL _isWorking; BOOL _mainNibLoaded; int _queryMode; + BOOL taskDisplayIsIndeterminate; + float taskProgressValue; + float taskDisplayLastValue; + float taskProgressValueDisplayInterval; + NSTimer *taskDrawTimer; + NSToolbar *mainToolbar; NSToolbarItem *chooseDatabaseToolbarItem; @@ -171,6 +183,15 @@ enum sp_current_query_mode - (IBAction)openCurrentConnectionInNewWindow:(id)sender; - (NSArray *)allDatabaseNames; +// Task progress and notification methods +- (void) startTaskWithDescription:(NSString *)description; +- (void) showTaskProgressLayer:(NSTimer *)theTimer; +- (void) setTaskDescription:(NSString *)description; +- (void) setTaskPercentage:(NSNumber *)taskPercentage; +- (void) setTaskProgressToIndeterminate; +- (void) endTask; +- (BOOL) isWorking; + // Encoding methods - (void)setConnectionEncoding:(NSString *)mysqlEncoding reloadingViews:(BOOL)reloadViews; - (NSString *)databaseEncoding; 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 @@ -1173,6 +1190,111 @@ _queryMode = theQueryMode; } +#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]; diff --git a/Source/TablesList.h b/Source/TablesList.h index 9a9272a3..d0349531 100644 --- a/Source/TablesList.h +++ b/Source/TablesList.h @@ -69,6 +69,9 @@ enum sp_table_types IBOutlet id tableNameField; IBOutlet id tableEncodingButton; IBOutlet id tableTypeButton; + IBOutlet id toolbarAddButton; + IBOutlet id toolbarActionsButton; + IBOutlet id toolbarReloadButton; IBOutlet id addTableButton; IBOutlet id tableRenameSheet; IBOutlet id tableRenameField; @@ -148,4 +151,8 @@ enum sp_table_types - (void) clearFilter; - (IBAction) updateFilter:(id)sender; +// Task interaction +- (void) startDocumentTaskForTab:(NSNotification *)aNotification; +- (void) endDocumentTaskForTab:(NSNotification *)aNotification; + @end diff --git a/Source/TablesList.m b/Source/TablesList.m index 348fb033..4e2aecef 100644 --- a/Source/TablesList.m +++ b/Source/TablesList.m @@ -1534,6 +1534,31 @@ [tablesListView selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO]; } +#pragma mark - +#pragma mark Task interaction + +/** + * Disable all table list interactive elements during an ongoing task. + */ +- (void) startDocumentTaskForTab:(NSNotification *)aNotification +{ + [tablesListView setEnabled:NO]; + [toolbarAddButton setEnabled:NO]; + [toolbarActionsButton setEnabled:NO]; + [toolbarReloadButton setEnabled:NO]; +} + +/** + * Enable all table list interactive elements after an ongoing task. + */ +- (void) endDocumentTaskForTab:(NSNotification *)aNotification +{ + [tablesListView setEnabled:YES]; + [toolbarAddButton setEnabled:YES]; + [toolbarActionsButton setEnabled:YES]; + [toolbarReloadButton setEnabled:YES]; +} + #pragma mark - #pragma mark SplitView Delegate Methods @@ -1594,6 +1619,15 @@ [tableListFilterSplitView setCollapsibleSubviewCollapsed:YES]; } + // Add observers for document task activity + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(startDocumentTaskForTab:) + name:SPDocumentTaskStartNotification + object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(endDocumentTaskForTab:) + name:SPDocumentTaskEndNotification + object:nil]; } /** @@ -1601,6 +1635,8 @@ */ - (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [tables release]; [tableTypes release]; if (isTableListFiltered && filteredTables) [filteredTables release]; diff --git a/Source/YRKSpinningProgressIndicator.h b/Source/YRKSpinningProgressIndicator.h new file mode 100644 index 00000000..fae46208 --- /dev/null +++ b/Source/YRKSpinningProgressIndicator.h @@ -0,0 +1,45 @@ +// +// YRKSpinningProgressIndicator.h +// +// Copyright 2009 Kelan Champagne. All rights reserved. +// + +#import + + +@interface YRKSpinningProgressIndicator : NSView { + int _position; + int _numFins; + + BOOL _isIndeterminate; + double _currentValue; + double _maxValue; + + BOOL _isAnimating; + NSThread *_animationThread; + + NSColor *_foreColor; + NSColor *_backColor; + BOOL _drawBackground; +} +- (void)animate:(id)sender; +- (void)stopAnimation:(id)sender; +- (void)startAnimation:(id)sender; + +- (NSColor *)foreColor; +- (void)setForeColor:(NSColor *)value; + +- (NSColor *)backColor; +- (void)setBackColor:(NSColor *)value; + +- (BOOL)drawBackground; +- (void)setDrawBackground:(BOOL)value; + +- (BOOL)isIndeterminate; +- (void)setIndeterminate:(BOOL)isIndeterminate; + +- (double)doubleValue; +- (void)setDoubleValue:(double)doubleValue; +- (double)maxValue; +- (void)setMaxValue:(double)maxValue; +@end diff --git a/Source/YRKSpinningProgressIndicator.m b/Source/YRKSpinningProgressIndicator.m new file mode 100644 index 00000000..f3ccab87 --- /dev/null +++ b/Source/YRKSpinningProgressIndicator.m @@ -0,0 +1,304 @@ +// +// YRKSpinningProgressIndicator.m +// +// Original drawing code by Kelan Champagne; forked by Rowan Beentje +// for fixes, determinate mode, and threaded drawing. +// +// Copyright (c) 2009, Kelan Champagne (http://yeahrightkeller.com) +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// * Neither the name of the nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY Kelan Champagne ''AS IS'' AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL Kelan Champagne BE LIABLE FOR ANY +// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#import "YRKSpinningProgressIndicator.h" + + +@interface YRKSpinningProgressIndicator (YRKSpinningProgressIndicatorPrivate) + +- (void) animateInBackgroundThread; + +@end + + +@implementation YRKSpinningProgressIndicator + +- (id)initWithFrame:(NSRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + _position = 0; + _numFins = 12; + _isAnimating = NO; + _animationThread = nil; + _foreColor = nil; + _backColor = nil; + _isIndeterminate = YES; + _currentValue = 0.0; + _maxValue = 100.0; + } + return self; +} + +- (void) dealloc { + if (_foreColor) [_foreColor release]; + if (_backColor) [_backColor release]; + if (_isAnimating) [self stopAnimation:self]; + [super dealloc]; +} + +- (void)viewDidMoveToWindow +{ + [super viewDidMoveToWindow]; + + if ([self window] == nil) { + // No window? View hierarchy may be going away. Ensure animation is stopped. + [self stopAnimation:self]; + } + else if (_isAnimating) { + [self stopAnimation:self]; + [self startAnimation:self]; + } +} + +- (void)drawRect:(NSRect)rect +{ + int i; + float alpha = 1.0; + + // Determine size based on current bounds + NSSize size = [self bounds].size; + float maxSize; + if(size.width >= size.height) + maxSize = size.height; + else + maxSize = size.width; + + // fill the background, if set + if(_drawBackground) { + [_backColor set]; + [NSBezierPath fillRect:[self bounds]]; + } + + CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; + [NSGraphicsContext saveGraphicsState]; + + // Move the CTM so 0,0 is at the center of our bounds + CGContextTranslateCTM(currentContext,[self bounds].size.width/2,[self bounds].size.height/2); + + if (_isIndeterminate) { + + // do initial rotation to start place + CGContextRotateCTM(currentContext, 3.14159*2/_numFins * _position); + + NSBezierPath *path = [[NSBezierPath alloc] init]; + float lineWidth = 0.08 * maxSize; // should be 2.75 for 32x32 + float lineStart = 0.234375 * maxSize; // should be 7.5 for 32x32 + float lineEnd = 0.421875 * maxSize; // should be 13.5 for 32x32 + [path setLineWidth:lineWidth]; + [path setLineCapStyle:NSRoundLineCapStyle]; + [path moveToPoint:NSMakePoint(0,lineStart)]; + [path lineToPoint:NSMakePoint(0,lineEnd)]; + + for (i=0; i<_numFins; i++) { + if(_isAnimating) { + [[_foreColor colorWithAlphaComponent:alpha] set]; + } else { + [[_foreColor colorWithAlphaComponent:0.2] set]; + } + + [path stroke]; + + // we draw all the fins by rotating the CTM, then just redraw the same segment again + CGContextRotateCTM(currentContext, 6.282185/_numFins); + alpha -= 1.0/_numFins; + } + [path release]; + + } else { + + float lineWidth = 1 + (0.01 * maxSize); + float circleRadius = (maxSize - lineWidth) / 2.1; + NSPoint circleCenter = NSMakePoint(0, 0); + [[_foreColor colorWithAlphaComponent:alpha] set]; + NSBezierPath *path = [[NSBezierPath alloc] init]; + [path setLineWidth:lineWidth]; + [path appendBezierPathWithOvalInRect:NSMakeRect(-circleRadius, -circleRadius, circleRadius*2, circleRadius*2)]; + [path stroke]; + [path release]; + path = [[NSBezierPath alloc] init]; + [path appendBezierPathWithArcWithCenter:circleCenter radius:circleRadius startAngle:90 endAngle:90-(360*(_currentValue/_maxValue)) clockwise:YES]; + [path lineToPoint:circleCenter] ; + [path fill]; + [path release]; + } + + [NSGraphicsContext restoreGraphicsState]; +} + +# pragma mark - +# pragma mark Subclass + +- (void)animate:(id)sender +{ + if(_position > 1) { + _position--; + } + else { + _position = _numFins; + } + [self display]; +} + +- (void) animateInBackgroundThread +{ + NSAutoreleasePool *animationPool = [[NSAutoreleasePool alloc] init]; + + // Set up the animation speed to subtly change with size > 32. + int animationDelay = 38000 + (2000 * ([self bounds].size.height / 32)); + int poolFlushCounter = 0; + + do { + [self animate:nil]; + usleep(animationDelay); + poolFlushCounter++; + if (poolFlushCounter > 256) { + [animationPool drain]; + animationPool = [[NSAutoreleasePool alloc] init]; + poolFlushCounter = 0; + } + } while (![[NSThread currentThread] isCancelled]); + + [animationPool release]; +} + +- (void)startAnimation:(id)sender +{ + _isAnimating = YES; + + _animationThread = [[NSThread alloc] initWithTarget:self selector:@selector(animateInBackgroundThread) object:nil]; + [_animationThread start]; +} + +- (void)stopAnimation:(id)sender +{ + _isAnimating = NO; + if (_animationThread) { + [_animationThread cancel]; + if (![_animationThread isFinished]) { + [[NSRunLoop currentRunLoop] runMode:NSModalPanelRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.05]]; + } + [_animationThread release], _animationThread = nil; + } + + [self setNeedsDisplay:YES]; +} + +# pragma mark Not Implemented + +- (void)setStyle:(NSProgressIndicatorStyle)style +{ + if (NSProgressIndicatorSpinningStyle != style) { + NSAssert(NO, @"Non-spinning styles not available."); + } +} + + +# pragma mark - +# pragma mark Accessors + +- (NSColor *)foreColor +{ + return [[_foreColor retain] autorelease]; +} + +- (void)setForeColor:(NSColor *)value +{ + if (_foreColor != value) { + [_foreColor release]; + _foreColor = [value copy]; + [self setNeedsDisplay:YES]; + } +} + +- (NSColor *)backColor +{ + return [[_backColor retain] autorelease]; +} + +- (void)setBackColor:(NSColor *)value +{ + if (_backColor != value) { + [_backColor release]; + _backColor = [value copy]; + [self setNeedsDisplay:YES]; + } +} + +- (BOOL)drawBackground +{ + return _drawBackground; +} + +- (void)setDrawBackground:(BOOL)value +{ + if (_drawBackground != value) { + _drawBackground = value; + } + [self setNeedsDisplay:YES]; +} + +- (BOOL)isIndeterminate +{ + return _isIndeterminate; +} + +- (void)setIndeterminate:(BOOL)isIndeterminate +{ + _isIndeterminate = isIndeterminate; + if (!_isIndeterminate && _isAnimating) [self stopAnimation:self]; + [self displayIfNeeded]; +} + +- (double)doubleValue +{ + return _currentValue; +} + +- (void)setDoubleValue:(double)doubleValue +{ + if (_isIndeterminate) _isIndeterminate = NO; + _currentValue = doubleValue; + [self displayIfNeeded]; +} + +- (double)maxValue +{ + return _maxValue; +} + +- (void)setMaxValue:(double)maxValue +{ + _maxValue = maxValue; + [self displayIfNeeded]; +} + +@end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index b7b4ac11..064f3180 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ 5822CAE110011C8000DCC3D6 /* ConnectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5822CADF10011C8000DCC3D6 /* ConnectionView.xib */; }; 5822D3091061833C00CE2157 /* SPCSVParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 5822D3081061833C00CE2157 /* SPCSVParser.m */; }; 582A01E9107C0C170027D42B /* SPNotLoaded.m in Sources */ = {isa = PBXBuildFile; fileRef = 582A01E8107C0C170027D42B /* SPNotLoaded.m */; }; + 582A05A9108A5CCF0027D42B /* ProgressIndicatorLayer.xib in Resources */ = {isa = PBXBuildFile; fileRef = 582A05A7108A5CCF0027D42B /* ProgressIndicatorLayer.xib */; }; 583B77D4103870C800B21F7E /* MCPStreamingResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 583B779810386B0200B21F7E /* MCPStreamingResult.m */; }; 5841423F0F97E11000A34B47 /* NoodleLineNumberView.m in Sources */ = {isa = PBXBuildFile; fileRef = 5841423E0F97E11000A34B47 /* NoodleLineNumberView.m */; }; 584192A1101E57BB0089807F /* NSMutableArray-MultipleSort.m in Sources */ = {isa = PBXBuildFile; fileRef = 584192A0101E57BB0089807F /* NSMutableArray-MultipleSort.m */; }; @@ -223,7 +224,7 @@ B5EAC0FD0EC87FF900CC579C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B5EAC0FC0EC87FF900CC579C /* Security.framework */; }; B5F4F7810F7BCF990059AE84 /* toolbar-switch-to-procedures.tiff in Resources */ = {isa = PBXBuildFile; fileRef = B5F4F7800F7BCF990059AE84 /* toolbar-switch-to-procedures.tiff */; }; BC01BCCF104024BE006BDEE7 /* SPEncodingPopupAccessory.m in Sources */ = {isa = PBXBuildFile; fileRef = BC01BCCE104024BE006BDEE7 /* SPEncodingPopupAccessory.m */; }; - BC05F1C5101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC05F1C4101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m */; }; + BC05F1C5101241DF008A97F8 /* YRKSpinningProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = BC05F1C4101241DF008A97F8 /* YRKSpinningProgressIndicator.m */; }; BC1847EA0FE6EC8400094BFB /* SPEditSheetTextView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1847E90FE6EC8400094BFB /* SPEditSheetTextView.m */; }; BC1E55C4100DC92200AAE9F0 /* table-view-small-square.tiff in Resources */ = {isa = PBXBuildFile; fileRef = BC1E55C3100DC92200AAE9F0 /* table-view-small-square.tiff */; }; BC29C37F10501EFD00DD6C6E /* SPQueryController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC29C37E10501EFD00DD6C6E /* SPQueryController.m */; }; @@ -529,6 +530,7 @@ 5822D3081061833C00CE2157 /* SPCSVParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPCSVParser.m; sourceTree = ""; }; 582A01E7107C0C170027D42B /* SPNotLoaded.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPNotLoaded.h; sourceTree = ""; }; 582A01E8107C0C170027D42B /* SPNotLoaded.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPNotLoaded.m; sourceTree = ""; }; + 582A05A8108A5CCF0027D42B /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Interfaces/English.lproj/ProgressIndicatorLayer.xib; sourceTree = ""; }; 583B779710386B0200B21F7E /* MCPStreamingResult.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = MCPStreamingResult.h; sourceTree = ""; }; 583B779810386B0200B21F7E /* MCPStreamingResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MCPStreamingResult.m; sourceTree = ""; }; 5841423D0F97E11000A34B47 /* NoodleLineNumberView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoodleLineNumberView.h; sourceTree = ""; }; @@ -620,8 +622,8 @@ B5F4F7800F7BCF990059AE84 /* toolbar-switch-to-procedures.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "toolbar-switch-to-procedures.tiff"; sourceTree = ""; }; BC01BCCD104024BE006BDEE7 /* SPEncodingPopupAccessory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPEncodingPopupAccessory.h; sourceTree = ""; }; BC01BCCE104024BE006BDEE7 /* SPEncodingPopupAccessory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPEncodingPopupAccessory.m; sourceTree = ""; }; - BC05F1C3101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMIndeterminateProgressIndicatorCell.h; sourceTree = ""; }; - BC05F1C4101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMIndeterminateProgressIndicatorCell.m; sourceTree = ""; }; + BC05F1C3101241DF008A97F8 /* YRKSpinningProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YRKSpinningProgressIndicator.h; sourceTree = ""; }; + BC05F1C4101241DF008A97F8 /* YRKSpinningProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YRKSpinningProgressIndicator.m; sourceTree = ""; }; BC1847E80FE6EC8400094BFB /* SPEditSheetTextView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPEditSheetTextView.h; sourceTree = ""; }; BC1847E90FE6EC8400094BFB /* SPEditSheetTextView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPEditSheetTextView.m; sourceTree = ""; }; BC1E55C3100DC92200AAE9F0 /* table-view-small-square.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = "table-view-small-square.tiff"; sourceTree = ""; }; @@ -1102,8 +1104,8 @@ 17E641710EF01F5C001BC333 /* GUI */ = { isa = PBXGroup; children = ( - BC05F1C3101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.h */, - BC05F1C4101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m */, + BC05F1C3101241DF008A97F8 /* YRKSpinningProgressIndicator.h */, + BC05F1C4101241DF008A97F8 /* YRKSpinningProgressIndicator.m */, 17E6417C0EF01FA8001BC333 /* CMCopyTable.h */, 17E6417D0EF01FA8001BC333 /* CMCopyTable.m */, 17E6417E0EF01FA8001BC333 /* CMImageView.h */, @@ -1227,6 +1229,7 @@ B58DA73B0FF8BBA500FDDACD /* PrintAccessory.xib */, B58DA7390FF8BB9E00FDDACD /* SSHQuestionDialog.xib */, 173C4360104455CA001F3A30 /* QueryFavoriteManager.xib */, + 582A05A7108A5CCF0027D42B /* ProgressIndicatorLayer.xib */, ); path = Interfaces; sourceTree = ""; @@ -1642,6 +1645,7 @@ BCB5619B106F8A1B00167321 /* EditorQuickLookTypes.plist in Resources */, BC675A17107203BA00C5ACD4 /* ContentFilterManager.xib in Resources */, BC65C3B2107CE3EE003F7B02 /* ImportAccessory.xib in Resources */, + 582A05A9108A5CCF0027D42B /* ProgressIndicatorLayer.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1773,7 +1777,7 @@ BC8C8532100E0A8000D7A129 /* SPTableView.m in Sources */, BC9F0881100FCF2C00A80D32 /* SPFieldEditorController.m in Sources */, 58D2E229101222670063EF1D /* SPTextAndLinkCell.m in Sources */, - BC05F1C5101241DF008A97F8 /* AMIndeterminateProgressIndicatorCell.m in Sources */, + BC05F1C5101241DF008A97F8 /* YRKSpinningProgressIndicator.m in Sources */, 4D90B79A101E0CDF00D116A1 /* SPUserManager.m in Sources */, 4D90B79E101E0CF200D116A1 /* SPUserManager.xcdatamodel in Sources */, 4D90B79F101E0CF200D116A1 /* SPUserMO.m in Sources */, @@ -1900,6 +1904,15 @@ name = ConnectionView.xib; sourceTree = ""; }; + 582A05A7108A5CCF0027D42B /* ProgressIndicatorLayer.xib */ = { + isa = PBXVariantGroup; + children = ( + 582A05A8108A5CCF0027D42B /* English */, + ); + name = ProgressIndicatorLayer.xib; + path = ..; + sourceTree = ""; + }; B52460D90F8EF93B00171639 /* Console.xib */ = { isa = PBXVariantGroup; children = ( -- cgit v1.2.3