diff options
-rw-r--r-- | Interfaces/English.lproj/GotoDatabaseDialog.xib | 117 | ||||
-rw-r--r-- | Interfaces/English.lproj/MainMenu.xib | 105 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.h | 3 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 19 | ||||
-rw-r--r-- | Source/SPGotoDatabaseController.h | 86 | ||||
-rw-r--r-- | Source/SPGotoDatabaseController.m | 223 | ||||
-rw-r--r-- | sequel-pro.xcodeproj/project.pbxproj | 10 |
7 files changed, 504 insertions, 59 deletions
diff --git a/Interfaces/English.lproj/GotoDatabaseDialog.xib b/Interfaces/English.lproj/GotoDatabaseDialog.xib new file mode 100644 index 00000000..310b74b0 --- /dev/null +++ b/Interfaces/English.lproj/GotoDatabaseDialog.xib @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="13E28" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none"> + <dependencies> + <deployment defaultVersion="1060" identifier="macosx"/> + <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/> + </dependencies> + <objects> + <customObject id="-2" userLabel="File's Owner" customClass="SPGotoDatabaseController"> + <connections> + <outlet property="cancelButton" destination="44U-6X-ZGG" id="dkD-wk-aid"/> + <outlet property="databaseListView" destination="cDW-lq-Q6e" id="aXN-gQ-VPQ"/> + <outlet property="okButton" destination="Qwd-4g-Aav" id="lhQ-gz-P3m"/> + <outlet property="searchField" destination="7dG-5r-Xs2" id="jrs-Y3-ixn"/> + <outlet property="window" destination="QvC-M9-y7g" id="3iD-lu-WNH"/> + </connections> + </customObject> + <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> + <customObject id="-3" userLabel="Application"/> + <window title="Go to Database" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" oneShot="NO" releasedWhenClosed="NO" showsToolbarButton="NO" visibleAtLaunch="NO" animationBehavior="default" id="QvC-M9-y7g"> + <windowStyleMask key="styleMask" titled="YES"/> + <rect key="contentRect" x="196" y="240" width="480" height="280"/> + <rect key="screenRect" x="0.0" y="0.0" width="1920" height="1178"/> + <value key="minSize" type="size" width="480" height="280"/> + <view key="contentView" id="EiT-Mj-1SZ"> + <rect key="frame" x="0.0" y="0.0" width="480" height="280"/> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <button verticalHuggingPriority="750" id="Qwd-4g-Aav"> + <rect key="frame" x="407" y="13" width="59" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/> + <buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="K2E-vc-mDT"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + <string key="keyEquivalent" base64-UTF8="YES"> +DQ +</string> + </buttonCell> + <connections> + <action selector="okClicked:" target="-2" id="yNe-4p-Qs8"/> + </connections> + </button> + <button verticalHuggingPriority="750" id="44U-6X-ZGG"> + <rect key="frame" x="14" y="13" width="82" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="6cJ-4a-khl"> + <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/> + <font key="font" metaFont="system"/> + <string key="keyEquivalent" base64-UTF8="YES"> +Gw +</string> + </buttonCell> + <connections> + <action selector="cancelClicked:" target="-2" id="HtW-wh-O9q"/> + </connections> + </button> + <searchField verticalHuggingPriority="750" id="7dG-5r-Xs2"> + <rect key="frame" x="20" y="238" width="440" height="22"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/> + <searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" borderStyle="bezel" placeholderString="Database Name" usesSingleLineMode="YES" bezelStyle="round" sendsSearchStringImmediately="YES" id="3iD-8e-Wt2"> + <font key="font" metaFont="system"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + </searchFieldCell> + <connections> + <action selector="searchChanged:" target="-2" id="keN-UZ-6QR"/> + <outlet property="delegate" destination="-2" id="DIs-zq-6Cv"/> + </connections> + </searchField> + <scrollView focusRingType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="LoZ-sS-bTj"> + <rect key="frame" x="20" y="50" width="440" height="180"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <clipView key="contentView" id="ip2-JF-i6U"> + <rect key="frame" x="1" y="1" width="438" height="178"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <subviews> + <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" selectionHighlightStyle="sourceList" alternatingRowBackgroundColors="YES" columnReordering="NO" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" typeSelect="NO" id="cDW-lq-Q6e"> + <rect key="frame" x="0.0" y="0.0" width="438" height="178"/> + <autoresizingMask key="autoresizingMask"/> + <size key="intercellSpacing" width="3" height="2"/> + <color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/> + <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> + <tableColumns> + <tableColumn editable="NO" width="435" minWidth="40" maxWidth="1000" id="Ift-DE-ytF"> + <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="Database"> + <font key="font" metaFont="smallSystem"/> + <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/> + </tableHeaderCell> + <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" refusesFirstResponder="YES" alignment="left" title="Text Cell" id="mE5-9u-hCv"> + <font key="font" metaFont="system"/> + <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> + <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/> + </textFieldCell> + <tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/> + </tableColumn> + </tableColumns> + <connections> + <outlet property="dataSource" destination="-2" id="O6w-uT-xK7"/> + </connections> + </tableView> + </subviews> + <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> + </clipView> + <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="H6G-xb-0Tc"> + <rect key="frame" x="1" y="164" width="423" height="15"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="GxF-Wp-RA1"> + <rect key="frame" x="424" y="17" width="15" height="147"/> + <autoresizingMask key="autoresizingMask"/> + </scroller> + </scrollView> + </subviews> + </view> + </window> + </objects> +</document> diff --git a/Interfaces/English.lproj/MainMenu.xib b/Interfaces/English.lproj/MainMenu.xib index f8d24d80..a8639839 100644 --- a/Interfaces/English.lproj/MainMenu.xib +++ b/Interfaces/English.lproj/MainMenu.xib @@ -1227,6 +1227,25 @@ <object class="NSMenu" key="NSSubmenu" id="762880388"> <string key="NSTitle">Database</string> <array class="NSMutableArray" key="NSMenuItems"> + <object class="NSMenuItem" id="859280893"> + <reference key="NSMenu" ref="762880388"/> + <string key="NSTitle">Go to Database…</string> + <string key="NSKeyEquiv">d</string> + <int key="NSKeyEquivModMask">1048576</int> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="325032718"/> + <reference key="NSMixedImage" ref="674471825"/> + </object> + <object class="NSMenuItem" id="346403677"> + <reference key="NSMenu" ref="762880388"/> + <bool key="NSIsDisabled">YES</bool> + <bool key="NSIsSeparator">YES</bool> + <string key="NSTitle"/> + <string key="NSKeyEquiv"/> + <int key="NSMnemonicLoc">2147483647</int> + <reference key="NSOnImage" ref="325032718"/> + <reference key="NSMixedImage" ref="674471825"/> + </object> <object class="NSMenuItem" id="838091116"> <reference key="NSMenu" ref="762880388"/> <string key="NSTitle">Add Database...</string> @@ -3151,6 +3170,14 @@ <string key="id">BUY-hF-nKy</string> </object> <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">showGotoDatabase:</string> + <reference key="source" ref="1005713010"/> + <reference key="destination" ref="859280893"/> + </object> + <string key="id">jS0-aP-Y7o</string> + </object> + <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> <string key="label">delegate</string> <reference key="source" ref="524643114"/> @@ -4145,6 +4172,8 @@ <reference ref="1042638490"/> <reference ref="1060677288"/> <reference ref="607642194"/> + <reference ref="859280893"/> + <reference ref="346403677"/> </array> <reference key="parent" ref="19149132"/> </object> @@ -4733,6 +4762,16 @@ <reference key="object" ref="221903071"/> <reference key="parent" ref="781540470"/> </object> + <object class="IBObjectRecord"> + <string key="id">8MG-hk-1qS</string> + <reference key="object" ref="859280893"/> + <reference key="parent" ref="762880388"/> + </object> + <object class="IBObjectRecord"> + <string key="id">Yzp-Qk-v7Y</string> + <reference key="object" ref="346403677"/> + <reference key="parent" ref="762880388"/> + </object> </array> </object> <dictionary class="NSMutableDictionary" key="flattenedProperties"> @@ -5266,6 +5305,7 @@ <boolean value="NO" key="864.showNotes"/> <string key="865.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="NO" key="865.showNotes"/> + <string key="8MG-hk-1qS.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="906.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="NO" key="906.showNotes"/> <string key="908.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> @@ -5362,6 +5402,7 @@ </object> <string key="998.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <boolean value="NO" key="998.showNotes"/> + <string key="Yzp-Qk-v7Y.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> <string key="nXE-rI-RyI.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> </dictionary> <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/> @@ -5372,47 +5413,6 @@ <object class="IBClassDescriber" key="IBDocument.Classes"> <array class="NSMutableArray" key="referencedPartialClassDescriptions"> <object class="IBPartialClassDescription"> - <string key="className">NSDocument</string> - <dictionary class="NSMutableDictionary" key="actions"> - <string key="printDocument:">id</string> - <string key="revertDocumentToSaved:">id</string> - <string key="runPageLayout:">id</string> - <string key="saveDocument:">id</string> - <string key="saveDocumentAs:">id</string> - <string key="saveDocumentTo:">id</string> - </dictionary> - <dictionary class="NSMutableDictionary" key="actionInfosByName"> - <object class="IBActionInfo" key="printDocument:"> - <string key="name">printDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo" key="revertDocumentToSaved:"> - <string key="name">revertDocumentToSaved:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo" key="runPageLayout:"> - <string key="name">runPageLayout:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo" key="saveDocument:"> - <string key="name">saveDocument:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo" key="saveDocumentAs:"> - <string key="name">saveDocumentAs:</string> - <string key="candidateClassName">id</string> - </object> - <object class="IBActionInfo" key="saveDocumentTo:"> - <string key="name">saveDocumentTo:</string> - <string key="candidateClassName">id</string> - </object> - </dictionary> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBProjectSource</string> - <string key="minorKey">./Classes/NSDocument.h</string> - </object> - </object> - <object class="IBPartialClassDescription"> <string key="className">NSTextView</string> <dictionary class="NSMutableDictionary" key="actions"> <string key="doDecomposedStringWithCanonicalMapping:">id</string> @@ -6877,6 +6877,7 @@ <string key="setDatabases:">id</string> <string key="showCreateTableSyntax:">id</string> <string key="showFilterTable:">id</string> + <string key="showGotoDatabase:">id</string> <string key="showMySQLHelp:">id</string> <string key="showNavigator:">id</string> <string key="showServerProcesses:">id</string> @@ -7044,6 +7045,10 @@ <string key="name">showFilterTable:</string> <string key="candidateClassName">id</string> </object> + <object class="IBActionInfo" key="showGotoDatabase:"> + <string key="name">showGotoDatabase:</string> + <string key="candidateClassName">id</string> + </object> <object class="IBActionInfo" key="showMySQLHelp:"> <string key="name">showMySQLHelp:</string> <string key="candidateClassName">id</string> @@ -9728,24 +9733,6 @@ <string key="minorKey">./Classes/SUUpdater.h</string> </object> </object> - <object class="IBPartialClassDescription"> - <string key="className">WebView</string> - <object class="NSMutableDictionary" key="actions"> - <string key="NS.key.0">reloadFromOrigin:</string> - <string key="NS.object.0">id</string> - </object> - <object class="NSMutableDictionary" key="actionInfosByName"> - <string key="NS.key.0">reloadFromOrigin:</string> - <object class="IBActionInfo" key="NS.object.0"> - <string key="name">reloadFromOrigin:</string> - <string key="candidateClassName">id</string> - </object> - </object> - <object class="IBClassDescriptionSource" key="sourceIdentifier"> - <string key="majorKey">IBProjectSource</string> - <string key="minorKey">./Classes/WebView.h</string> - </object> - </object> </array> </object> <int key="IBDocument.localizationMode">0</int> diff --git a/Source/SPDatabaseDocument.h b/Source/SPDatabaseDocument.h index 218f3bc7..a67619e8 100644 --- a/Source/SPDatabaseDocument.h +++ b/Source/SPDatabaseDocument.h @@ -55,6 +55,7 @@ @class SPDatabaseStructure; @class SPMySQLConnection; @class SPCharsetCollationHelper; +@class SPGotoDatabaseController; #import "SPDatabaseContentViewDelegate.h" #import "SPConnectionControllerDelegateProtocol.h" @@ -280,6 +281,7 @@ BOOL windowTitleStatusViewIsVisible; #endif SPDatabaseStructure *databaseStructureRetrieval; + SPGotoDatabaseController *gotoDatabaseController; } #ifdef SP_CODA /* ivars */ @@ -352,6 +354,7 @@ - (IBAction)showServerVariables:(id)sender; - (IBAction)showServerProcesses:(id)sender; - (IBAction)openCurrentConnectionInNewWindow:(id)sender; +- (IBAction)showGotoDatabase:(id)sender; #endif - (NSArray *)allDatabaseNames; - (NSArray *)allSystemDatabaseNames; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 330716c3..9a736f90 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -109,6 +109,7 @@ enum { #endif #import "SPCharsetCollationHelper.h" +#import "SPGotoDatabaseController.h" #import <SPMySQL/SPMySQL.h> @@ -206,6 +207,7 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; mySQLVersion = nil; allDatabases = nil; allSystemDatabases = nil; + gotoDatabaseController = nil; #ifndef SP_CODA /* init ivars */ mainToolbar = nil; @@ -1131,6 +1133,22 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; return [[SPNavigatorController sharedNavigatorController] allSchemaKeysForConnection:[self connectionID]]; } +- (IBAction)showGotoDatabase:(id)sender +{ + if(!gotoDatabaseController) { + gotoDatabaseController = [[SPGotoDatabaseController alloc] init]; + } + + NSMutableArray *dbList = [[NSMutableArray alloc] init]; + [dbList addObjectsFromArray:[self allSystemDatabaseNames]]; + [dbList addObjectsFromArray:[self allDatabaseNames]]; + [gotoDatabaseController setDatabaseList:[dbList autorelease]]; + + if([gotoDatabaseController runModal]) { + [self selectDatabase:[gotoDatabaseController selectedDatabase] item:nil]; + } +} + #ifndef SP_CODA /* console and navigator methods */ #pragma mark - @@ -6269,6 +6287,7 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; [allDatabases release]; [allSystemDatabases release]; + [gotoDatabaseController release]; #ifndef SP_CODA /* dealloc ivars */ [undoManager release]; [printWebView release]; diff --git a/Source/SPGotoDatabaseController.h b/Source/SPGotoDatabaseController.h new file mode 100644 index 00000000..99dfc289 --- /dev/null +++ b/Source/SPGotoDatabaseController.h @@ -0,0 +1,86 @@ +// +// GotoDatbaseController.h +// sequel-pro +// +// Created by Max Lohrmann on 12.10.14. +// Copyright (c) 2014 Max Lohrmann. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// More info at <https://github.com/sequelpro/sequelpro> + +#import <Cocoa/Cocoa.h> +@class SPDatabaseDocument; + +/** + * This class provides a dialog with a single-column table view and a + * search field. It can be used for finding databases by name and/or faster, + * keyboard-based navigation between databases. The dialog also enables + * jumping to a database by C&P-ing its full name. + */ +@interface SPGotoDatabaseController : NSWindowController <NSTableViewDataSource,NSControlTextEditingDelegate> { + IBOutlet NSSearchField *searchField; + IBOutlet NSButton *okButton; + IBOutlet NSButton *cancelButton; + IBOutlet NSTableView *databaseListView; + + NSMutableArray *unfilteredList; + NSMutableArray *filteredList; + BOOL isFiltered; +} + +/** + * Specifies whether custom names (i.e. names that were not in the list supplied + * by setDatabaseList:) will be allowed. This is useful if it has to be assumed + * that the list of databases is not exhaustive (eg. databases added after fetching + * the database list). + */ +@property BOOL allowCustomNames; + +/** + * Set the list of databases the user can pick from. + * @param list An array of NSStrings + * + * This method must be called before runModal. The list will not be updated + * when the dialog is on screen. + */ +- (void)setDatabaseList:(NSArray *)list; + +/** + * Retrieve the user selection. + * @return The selected database or nil, if there is no selection + * + * This method retrieves the database selected by the user. Note that this is + * not neccesarily one of the objects which were passed in, if allowCustomNames + * is enabled. The return value of this function is undefined after calling + * setDatabaseList:! + */ +- (NSString *)selectedDatabase; + +/** + * Starts displaying the dialog as application modal. + * @return YES if the user pressed "OK", NO otherwise + * + * This method will only return once the dialog was closed again. + */ +- (BOOL)runModal; +@end diff --git a/Source/SPGotoDatabaseController.m b/Source/SPGotoDatabaseController.m new file mode 100644 index 00000000..0c6cbef0 --- /dev/null +++ b/Source/SPGotoDatabaseController.m @@ -0,0 +1,223 @@ +// +// GotoDatbaseController.m +// sequel-pro +// +// Created by Max Lohrmann on 12.10.14. +// Copyright (c) 2014 Max Lohrmann. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +// More info at <https://github.com/sequelpro/sequelpro> + +#import "SPGotoDatabaseController.h" +#import "SPDatabaseDocument.h" + +@interface SPGotoDatabaseController (Private) +- (void)_buildHightlightedFilterList:(NSString *)filter didFindExactMatch:(BOOL *)exactMatch; + +- (IBAction)okClicked:(id)sender; +- (IBAction)cancelClicked:(id)sender; +- (IBAction)searchChanged:(id)sender; +@end + +@implementation SPGotoDatabaseController + +- (id)init +{ + self = [super initWithWindowNibName:@"GotoDatabaseDialog"]; + if (self) { + unfilteredList = [[NSMutableArray alloc] init]; + filteredList = [[NSMutableArray alloc] init]; + isFiltered = NO; + [self setAllowCustomNames:YES]; + } + return self; +} + +#pragma mark - +#pragma mark IBAction + +- (IBAction)okClicked:(id)sender +{ + [NSApp stopModalWithCode:YES]; + [[self window] orderOut:nil]; +} + +- (IBAction)cancelClicked:(id)sender +{ + [NSApp stopModalWithCode:NO]; + [[self window] orderOut:nil]; +} + +- (IBAction)searchChanged:(id)sender +{ + [filteredList removeAllObjects]; + NSString *newFilter = [searchField stringValue]; + if(!newFilter || [newFilter isEqualToString:@""]) { + isFiltered = NO; + } + else { + isFiltered = YES; + BOOL exactMatch = NO; + [self _buildHightlightedFilterList:newFilter didFindExactMatch:&exactMatch]; + //always add the search string to the end of the list (in case the user + //wants to switch to a DB not in the list) unless there was an exact match + if([self allowCustomNames] && !exactMatch) { + NSMutableAttributedString *searchValue = [[NSMutableAttributedString alloc] initWithString:newFilter]; + [searchValue applyFontTraits:NSItalicFontMask range:NSMakeRange(0, [newFilter length])]; + [filteredList addObject:[searchValue autorelease]]; + } + } + [databaseListView reloadData]; + //ensure we have a selection + if([databaseListView selectedRow] < 0) + [databaseListView selectRowIndexes:[NSIndexSet indexSetWithIndex:0] byExtendingSelection:NO]; + + [okButton setEnabled:([databaseListView selectedRow] >= 0)]; +} + +#pragma mark - +#pragma mark Public + +- (NSString *)selectedDatabase { + NSInteger row = [databaseListView selectedRow]; + id attrValue; + if(isFiltered) { + attrValue = [filteredList objectOrNilAtIndex:row]; + } + else { + attrValue = [unfilteredList objectOrNilAtIndex:row]; + } + if([attrValue isKindOfClass:[NSAttributedString class]]) + return [attrValue string]; + return attrValue; +} + +- (void)setDatabaseList:(NSArray *)list +{ + //update list of databases + [unfilteredList removeAllObjects]; + [unfilteredList addObjectsFromArray:list]; +} + +- (BOOL)runModal +{ + //NSWindowController is lazy with loading nibs + [self window]; + + //reset the search field + [searchField setStringValue:@""]; + [self searchChanged:nil]; + //give focus to search field + [[self window] makeFirstResponder:searchField]; + //start modal dialog + return [NSApp runModalForWindow:[self window]]; +} + +#pragma mark - +#pragma mark Private + +- (void)_buildHightlightedFilterList:(NSString *)filter didFindExactMatch:(BOOL *)exactMatch +{ + NSDictionary *attrs = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSColor colorWithCalibratedRed:249/255.0 green:247/255.0 blue:62/255.0 alpha:0.5],NSBackgroundColorAttributeName, + [NSColor colorWithCalibratedRed:180/255.0 green:164/255.0 blue:31/255.0 alpha:1.0],NSUnderlineColorAttributeName, + [NSNumber numberWithInt:NSUnderlineStyleSingle],NSUnderlineStyleAttributeName, + nil]; + + for(NSString *db in unfilteredList) { + NSRange match = [db rangeOfString:filter]; + if(match.location == NSNotFound) + continue; + //check for exact match? + if(exactMatch && !*exactMatch) { + if(match.location == 0 && match.length == [db length]) + *exactMatch = YES; + } + + NSMutableAttributedString *attrMatch = [[NSMutableAttributedString alloc] initWithString:db]; + [attrMatch setAttributes:attrs range:match]; + [filteredList addObject:[attrMatch autorelease]]; + } + + [attrs release]; +} + +#pragma mark - +#pragma mark NSTableViewDataSource + +- (NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView +{ + if(!isFiltered) { + return [unfilteredList count]; + } + else { + return [filteredList count]; + } +} + +- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex +{ + if(!isFiltered) + return [unfilteredList objectAtIndex:rowIndex]; + else + return [filteredList objectAtIndex:rowIndex]; +} + +#pragma mark - +#pragma mark NSControlTextEditingDelegate + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector +{ + //the ESC key will usually clear the search field. we want to close the dialog + if(commandSelector == @selector(cancelOperation:)) { + [cancelButton performClick:control]; + return YES; + } + //arrow down/up will usually go to start/end of the text field. we want to change the selected table row. + if(commandSelector == @selector(moveDown:)) { + [databaseListView selectRowIndexes:[NSIndexSet indexSetWithIndex:([databaseListView selectedRow]+1)] byExtendingSelection:NO]; + return YES; + } + if(commandSelector == @selector(moveUp:)) { + [databaseListView selectRowIndexes:[NSIndexSet indexSetWithIndex:([databaseListView selectedRow]-1)] byExtendingSelection:NO]; + return YES; + } + //forward return to OK button (enter will not be caught by search field) + if(commandSelector == @selector(insertNewline:)) { + [okButton performClick:control]; + return YES; + } + + return NO; +} + +#pragma mark - + +- (void)dealloc +{ + [unfilteredList release], unfilteredList = nil; + [filteredList release], filteredList = nil; + [super dealloc]; +} + +@end diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index 073ad76f..0014bc2f 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -179,6 +179,8 @@ 4DECC48F0EC2B436008D359E /* Sparkle.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3320EC2A170008D359E /* Sparkle.framework */; }; 4DECC4910EC2B436008D359E /* Growl.framework in Copy Frameworks */ = {isa = PBXBuildFile; fileRef = 4DECC3340EC2A170008D359E /* Growl.framework */; }; 501B1D181728A3DA0017C92E /* SPCharsetCollationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 501B1D171728A3DA0017C92E /* SPCharsetCollationHelper.m */; }; + 50A9F8AD19EAD4860053E571 /* GotoDatabaseDialog.xib in Resources */ = {isa = PBXBuildFile; fileRef = 50A9F8AC19EAD4860053E571 /* GotoDatabaseDialog.xib */; }; + 50A9F8B119EAD4B90053E571 /* SPGotoDatabaseController.m in Sources */ = {isa = PBXBuildFile; fileRef = 50A9F8B019EAD4B90053E571 /* SPGotoDatabaseController.m */; }; 50E217B318174246009D3580 /* SPColorSelectorView.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E217B218174246009D3580 /* SPColorSelectorView.m */; }; 50E217B618174280009D3580 /* SPFavoriteColorSupport.m in Sources */ = {isa = PBXBuildFile; fileRef = 50E217B518174280009D3580 /* SPFavoriteColorSupport.m */; }; 5806B76411A991EC00813A88 /* SPDocumentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5806B76311A991EC00813A88 /* SPDocumentController.m */; }; @@ -879,6 +881,9 @@ 4DECC3340EC2A170008D359E /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Growl.framework; path = Frameworks/Growl.framework; sourceTree = "<group>"; }; 501B1D161728A3DA0017C92E /* SPCharsetCollationHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPCharsetCollationHelper.h; sourceTree = "<group>"; }; 501B1D171728A3DA0017C92E /* SPCharsetCollationHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPCharsetCollationHelper.m; sourceTree = "<group>"; }; + 50A9F8AC19EAD4860053E571 /* GotoDatabaseDialog.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = GotoDatabaseDialog.xib; path = English.lproj/GotoDatabaseDialog.xib; sourceTree = "<group>"; }; + 50A9F8AF19EAD4B90053E571 /* SPGotoDatabaseController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPGotoDatabaseController.h; sourceTree = "<group>"; }; + 50A9F8B019EAD4B90053E571 /* SPGotoDatabaseController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPGotoDatabaseController.m; sourceTree = "<group>"; }; 50E217B118174246009D3580 /* SPColorSelectorView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPColorSelectorView.h; sourceTree = "<group>"; }; 50E217B218174246009D3580 /* SPColorSelectorView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPColorSelectorView.m; sourceTree = "<group>"; }; 50E217B418174280009D3580 /* SPFavoriteColorSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPFavoriteColorSupport.h; sourceTree = "<group>"; }; @@ -1583,6 +1588,8 @@ 17846B9D170C95D800414499 /* Process List */, 17381853151FB29C0078FFE2 /* User Manager */, 1713C73D140D88D400CFD461 /* Query Controller */, + 50A9F8AF19EAD4B90053E571 /* SPGotoDatabaseController.h */, + 50A9F8B019EAD4B90053E571 /* SPGotoDatabaseController.m */, ); name = "Subview Controllers"; sourceTree = "<group>"; @@ -2202,6 +2209,7 @@ 1792C13010AD752100ABE758 /* DatabaseServerVariables.xib */, 58C3507310B9ADEA00D37E14 /* ContentPaginationView.xib */, 17A7773611C52E61001E27B4 /* IndexesView.xib */, + 50A9F8AC19EAD4860053E571 /* GotoDatabaseDialog.xib */, ); path = Interfaces; sourceTree = "<group>"; @@ -2914,6 +2922,7 @@ C9AD7C7C1676158C00234EEE /* toolbar-switch-to-sql@2x.png in Resources */, C9AD7C7F167619B400234EEE /* button_refresh.png in Resources */, C9AD7C80167619B400234EEE /* button_refresh@2x.png in Resources */, + 50A9F8AD19EAD4860053E571 /* GotoDatabaseDialog.xib in Resources */, C9AD7C8316761B3300234EEE /* button_action.png in Resources */, C9AD7C8416761B3300234EEE /* button_action@2x.png in Resources */, C9AD7C891676204300234EEE /* button_info_pane_hide.png in Resources */, @@ -3085,6 +3094,7 @@ 17E6415A0EF01EF6001BC333 /* SPDatabaseDocument.m in Sources */, 17E6415B0EF01EF6001BC333 /* SPDataImport.m in Sources */, 17E6415C0EF01EF6001BC333 /* SPTableStructure.m in Sources */, + 50A9F8B119EAD4B90053E571 /* SPGotoDatabaseController.m in Sources */, 17E641640EF01F15001BC333 /* SPTableInfo.m in Sources */, 17E641650EF01F15001BC333 /* SPTablesList.m in Sources */, 17E6416C0EF01F37001BC333 /* ImageAndTextCell.m in Sources */, |