diff options
author | dmoagx <post@wickenrode.com> | 2013-10-23 00:34:52 +0000 |
---|---|---|
committer | dmoagx <post@wickenrode.com> | 2013-10-23 00:34:52 +0000 |
commit | b3b87db97d6b607ed78a671115e3e56a76077503 (patch) | |
tree | 4b8241025d09961037dcadfc8adffe9f4ee28741 /Source | |
parent | 546f436290721d208381769bef646a8ab9d42212 (diff) | |
download | sequelpro-b3b87db97d6b607ed78a671115e3e56a76077503.tar.gz sequelpro-b3b87db97d6b607ed78a671115e3e56a76077503.tar.bz2 sequelpro-b3b87db97d6b607ed78a671115e3e56a76077503.zip |
* This change adds basic tab coloring support for favorites - ** POC / NEEDS REVIEW **
Known issues:
* There might be additional colors be shown when dragging tabs between windows
* The color set might need fine tuning
* Coloring of items in the favorite outline view is not yet handled
Diffstat (limited to 'Source')
-rw-r--r-- | Source/SPColorSelectorView.h | 81 | ||||
-rw-r--r-- | Source/SPColorSelectorView.m | 436 | ||||
-rw-r--r-- | Source/SPConnectionController.h | 8 | ||||
-rw-r--r-- | Source/SPConnectionController.m | 31 | ||||
-rw-r--r-- | Source/SPConnectionControllerDelegate.m | 8 | ||||
-rw-r--r-- | Source/SPConnectionControllerInitializer.m | 16 | ||||
-rw-r--r-- | Source/SPConstants.h | 2 | ||||
-rw-r--r-- | Source/SPConstants.m | 2 | ||||
-rw-r--r-- | Source/SPDatabaseDocument.m | 6 | ||||
-rw-r--r-- | Source/SPFavoriteColorSupport.h | 61 | ||||
-rw-r--r-- | Source/SPFavoriteColorSupport.m | 96 | ||||
-rw-r--r-- | Source/SPWindowController.m | 1 |
12 files changed, 741 insertions, 7 deletions
diff --git a/Source/SPColorSelectorView.h b/Source/SPColorSelectorView.h new file mode 100644 index 00000000..5e6a2204 --- /dev/null +++ b/Source/SPColorSelectorView.h @@ -0,0 +1,81 @@ +// +// $Id$ +// +// SPColorSelectorView.h +// sequel-pro +// +// Created by Max Lohrmann on 2013-10-20 +// Copyright (c) 2013 Max Lohrmann. All rights reserved. +// +// Adapted from: +// CCTColorLabelMenuItemView.h +// LabelPickerMenu +// +// Copyright (c) 2010 Dan Messing. All Rights Reserved. +// +// Based on: +// TrackView.h +// MenuItemView example code +// +// Copyright (C) Apple Inc. 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 <http://code.google.com/p/sequel-pro/> + + +#import <Foundation/Foundation.h> + +@interface SPColorSelectorView : NSView { + + NSMutableArray* trackingAreas; + + NSInteger selectedTag; // indicates the selected tag + NSInteger hoverTag; // indicated the currently tracked tag + BOOL trackEntered; // indicates we are currently inside a label tracking area + + id observer; // used for reverse notification with cocoa bindings + NSString *observerKeyPath; + + IBOutlet id delegate; + + NSArray *colorList; +} + +@property (nonatomic,readwrite,assign) NSInteger selectedTag; + +/** + * Provide a list of (NSColor *) objects (at most 7) which will be displayed in the view + */ +@property (readwrite,copy) NSArray *colorList; + +@end + +@interface NSObject (SPColorSelectorViewDelegate) + +/** + * Called on a delegate when the selection did (really) change + * @param aView The changed view + */ +- (void)colorSelectorDidChange:(SPColorSelectorView *)aView; + +@end diff --git a/Source/SPColorSelectorView.m b/Source/SPColorSelectorView.m new file mode 100644 index 00000000..9e80b79c --- /dev/null +++ b/Source/SPColorSelectorView.m @@ -0,0 +1,436 @@ +// +// $Id$ +// +// SPColorSelectorView.m +// sequel-pro +// +// Created by Max Lohrmann on 2013-10-20 +// Copyright (c) 2013 Max Lohrmann. All rights reserved. +// +// Adapted from: +// CCTColorLabelMenuItemView.m +// LabelPickerMenu +// +// Copyright (c) 2010 Dan Messing. All Rights Reserved. +// +// Based on: +// TrackView.m +// MenuItemView example code +// +// Copyright (C) Apple Inc. 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 <http://code.google.com/p/sequel-pro/> + +#import "SPColorSelectorView.h" + +@interface SPColorSelectorView (Private) + +- (void)setupTrackingAreas; + +@end + +@implementation SPColorSelectorView + +@synthesize selectedTag; +@synthesize colorList; + +// key for dictionary in NSTrackingAreas's userInfo +NSString* kTrackerKey = @"whichTracker"; + +// key values for dictionary in NSTrackingAreas's userInfo, +// which tracking area is being tracked +enum trackingAreaIDs +{ + kTrackingAreaNone = -1, + kTrackingArea0, + kTrackingArea1, + kTrackingArea2, + kTrackingArea3, + kTrackingArea4, + kTrackingArea5, + kTrackingArea6 +}; + +// ------------------------------------------------------------------------------- +// initWithFrame: +// +// Setup the tracking areas for each colored dot. +// ------------------------------------------------------------------------------- +- (id)initWithFrame:(NSRect)frameRect +{ + if ( self = [super initWithFrame:frameRect] ) + { + selectedTag = kTrackingAreaNone; //we start out with no selection + observer = nil; + colorList = nil; + [self setupTrackingAreas]; + + //set ourselves as observer of selectedTag (need to mark view dirty) + [self addObserver:self forKeyPath:@"selectedTag" options:0 context:nil]; + } + return self; +} + +- (void)bind:(NSString *)binding toObject:(id)observableObject withKeyPath:(NSString *)keyPath options:(NSDictionary *)options +{ + if([binding isEqualToString:@"selectedTag"]) { + [observableObject addObserver:self forKeyPath:keyPath options:0 context:nil]; + observer = [observableObject retain]; + observerKeyPath = [keyPath copy]; + } + else { + [super bind:binding toObject:observableObject withKeyPath:keyPath options:options]; + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context +{ + if(object == self) { + [self setNeedsDisplay:YES]; + } + else if(object == observer) { + // You passed the binding identifier as the context when registering + // as an observer--use that to decide what to update... + + id newValue = [observer valueForKeyPath:observerKeyPath]; + + NSNumber *num = (NSNumber *)newValue; + + [self setSelectedTag:[num integerValue]]; + } +} + +// ------------------------------------------------------------------------------- +// dealloc: +// ------------------------------------------------------------------------------- +-(void)dealloc +{ + [trackingAreas release]; + [super dealloc]; +} + + +// ------------------------------------------------------------------------------- +// Returns the rectangle corresponding to the tracking area. +// ------------------------------------------------------------------------------- +- (NSRect)rectForColorViewAtIndex:(NSInteger)index +{ + CGFloat baseY = 2.0; + CGFloat baseX = 2.0; + + CGFloat marginR = 5.0; + + CGFloat width = 16.0; + CGFloat height = 16.0; + + NSRect returnRect = NSZeroRect; + switch (index) + { + case kTrackingAreaNone: + returnRect = NSMakeRect(baseX, baseY, width, height); + break; + + case kTrackingArea0: + returnRect = NSMakeRect(baseX+1*(width+marginR), baseY, width, height); + break; + + case kTrackingArea1: + returnRect = NSMakeRect(baseX+2*(width+marginR), baseY, width, height); + break; + + case kTrackingArea2: + returnRect = NSMakeRect(baseX+3*(width+marginR), baseY, width, height); + break; + + case kTrackingArea3: + returnRect = NSMakeRect(baseX+4*(width+marginR), baseY, width, height); + break; + + case kTrackingArea4: + returnRect = NSMakeRect(baseX+5*(width+marginR), baseY, width, height); + break; + + case kTrackingArea5: + returnRect = NSMakeRect(baseX+6*(width+marginR), baseY, width, height); + break; + + case kTrackingArea6: + returnRect = NSMakeRect(baseX+7*(width+marginR), baseY, width, height); + break; + } + return returnRect; +} + +// ------------------------------------------------------------------------------- +// Returns the color gradient corresponding to the tag. These colours were +// chosen to appear similar to those in Aperture 3. +// ------------------------------------------------------------------------------- + +- (NSGradient *)gradientForTag:(NSInteger)colorTag +{ + NSGradient *gradient = nil; + + //find base color item + NSColor *baseColor = (NSColor *)[colorList objectAtIndex:colorTag]; + if(!baseColor) + return nil; + + //create hightlight and shadow variants of color + NSColor *shadowColor = [baseColor shadowWithLevel:0.22]; + NSColor *highlightColor = [baseColor highlightWithLevel:0.22]; + + //build gradient + gradient = [[NSGradient alloc] initWithColorsAndLocations: + highlightColor, 0.0, + baseColor, 0.5, + shadowColor, 1.0, nil]; + + return [gradient autorelease]; +} + +// ------------------------------------------------------------------------------- +// setupTrackingAreas: +// ------------------------------------------------------------------------------- +- (void)setupTrackingAreas +{ + if (trackingAreas == nil) + { + trackingAreas = [NSMutableArray array]; // keep all tracking areas in an array + + // determine the tracking options + NSTrackingAreaOptions trackingOptions = NSTrackingEnabledDuringMouseDrag | + NSTrackingMouseEnteredAndExited | + NSTrackingActiveInActiveApp | + NSTrackingActiveAlways; + + NSInteger index; + for (index = kTrackingAreaNone; index <= kTrackingArea6; index++) + { + // make tracking data (to be stored in NSTrackingArea's userInfo) so we can later determine which tracking area is focused on + // + NSDictionary* trackerData = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInteger:index], kTrackerKey, nil]; + NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[self rectForColorViewAtIndex:index] + options:trackingOptions + owner:self + userInfo:trackerData]; + + [trackingAreas addObject:trackingArea]; // keep track of this tracking area for later disposal + [self addTrackingArea: trackingArea]; // add the tracking area to the view/window + } + } +} + +#pragma mark - +#pragma mark Custom Drawing + +// ------------------------------------------------------------------------------- +// drawRect:rect +// +// Examine all the sub-view colored dots and color them with their appropriate colors. +// ------------------------------------------------------------------------------- +-(void)drawRect:(NSRect)rect +{ + // see if we should be drawing any of the tags as already selected + NSInteger currentlySelectedTag = [self selectedTag]; + + + NSInteger index; + for (index = kTrackingAreaNone; index <= kTrackingArea6; index++) + { + NSRect colorSquareRect = [self rectForColorViewAtIndex:index]; + + //make sure the color at index is actually defined + if(index >= 0 && [colorList objectAtIndex:index] == nil) + continue; + + //do not draw a selection around the X item + if (index > kTrackingAreaNone && index == currentlySelectedTag) + { + NSBezierPath *highlightPath = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(colorSquareRect, -1.5, -1.5)]; + [[NSColor colorWithCalibratedRed:0.76 green:0.78 blue:0.82 alpha:1.0] set]; + [highlightPath fill]; + + [[NSColor colorWithCalibratedWhite:0.6 alpha:1.0] set]; + [highlightPath setLineWidth:1.0]; + [highlightPath stroke]; + + } + else if (index == hoverTag && trackEntered) + { + // if we are tracking inside any tag, we want outline the color choice + NSBezierPath *highlightPath = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(colorSquareRect, -1.5, -1.5)]; + [[NSColor colorWithCalibratedWhite:0.94 alpha:1.0] set]; + [highlightPath fill]; + + [[NSColor colorWithCalibratedWhite:0.6 alpha:1.0] set]; + [highlightPath setLineWidth:1.0]; + [highlightPath stroke]; + } + + if(index == kTrackingAreaNone) { + + + [[NSColor disabledControlTextColor] set]; + //draw an X + NSBezierPath *left = [NSBezierPath bezierPath]; + [left setLineWidth:3.0]; + [left setLineCapStyle:NSButtLineCapStyle]; + [left moveToPoint:NSMakePoint(colorSquareRect.origin.x+4.0, colorSquareRect.origin.y+4.0)]; + [left lineToPoint:NSMakePoint(colorSquareRect.origin.x+12.0, colorSquareRect.origin.y+12.0)]; + [left moveToPoint:NSMakePoint(colorSquareRect.origin.x+12.0, colorSquareRect.origin.y+4.0)]; + [left lineToPoint:NSMakePoint(colorSquareRect.origin.x+4.0, colorSquareRect.origin.y+12.0)]; + [left stroke]; + + } + else { + // draw the gradient dot + NSGradient *gradient = [self gradientForTag:index]; + NSRect dotRect = NSInsetRect(colorSquareRect, 2.0, 2.0); + NSBezierPath *circlePath = [NSBezierPath bezierPathWithOvalInRect:dotRect]; + [gradient drawInBezierPath:circlePath angle:-90.0]; + + + // draw a highlight + + // top edge outline + gradient = [[NSGradient alloc] initWithColorsAndLocations: + [NSColor colorWithCalibratedWhite:1.0 alpha:0.18], 0.0, + [NSColor colorWithCalibratedWhite:1.0 alpha:0.0], 0.6, nil]; + circlePath = [NSBezierPath bezierPathWithOvalInRect:NSInsetRect(dotRect, 1.0, 1.0)]; + [circlePath appendBezierPath:[NSBezierPath bezierPathWithOvalInRect:NSMakeRect(dotRect.origin.x+1.0, dotRect.origin.y-2.0, dotRect.size.width-2.0, dotRect.size.height)]]; + [circlePath setWindingRule:NSEvenOddWindingRule]; + [gradient drawInBezierPath:circlePath angle:-90.0]; + [gradient release]; + + // top center gloss + gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.18] + endingColor:[NSColor colorWithCalibratedWhite:1.0 alpha:0.0]]; + [gradient drawFromCenter:NSMakePoint(NSMidX(dotRect), NSMaxY(dotRect) - 2.0) + radius:0.0 + toCenter:NSMakePoint(NSMidX(dotRect), NSMaxY(dotRect) - 2.0) + radius:4.0 + options:0]; + [gradient release]; + + // draw a dark outline + circlePath = [NSBezierPath bezierPathWithOvalInRect:dotRect]; + gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.12] + endingColor:[NSColor colorWithCalibratedWhite:0.0 alpha:0.46]]; + [circlePath appendBezierPath:[NSBezierPath bezierPathWithOvalInRect:NSInsetRect(dotRect, 1.0, 1.0)]]; + [circlePath setWindingRule:NSEvenOddWindingRule]; + [gradient drawInBezierPath:circlePath angle:-90.0]; + [gradient release]; + } + + + } + +} + + +#pragma mark - +#pragma mark Mouse Handling + +// ------------------------------------------------------------------------------- +// getTrackerIDFromDict:dict +// +// Used in obtaining dictionary entry info from the 'userData', used by each +// mouse event method. It helps determine which tracking area is being tracked. +// ------------------------------------------------------------------------------- +- (int)getTrackerIDFromDict:(NSDictionary*)dict +{ + id whichTracker = [dict objectForKey: kTrackerKey]; + return [whichTracker intValue]; +} + +// ------------------------------------------------------------------------------- +// mouseEntered:event +// +// Because we installed NSTrackingArea to our NSImageView, this method will be called. +// ------------------------------------------------------------------------------- +- (void)mouseEntered:(NSEvent*)event +{ + // which tracking area is being tracked? + hoverTag = [self getTrackerIDFromDict:[event userData]]; + trackEntered = YES; + + [self setNeedsDisplay:YES]; // force update the currently tracked tag back to its original color +} + +// ------------------------------------------------------------------------------- +// mouseExited:event +// +// Because we installed NSTrackingArea to our NSImageView, this method will be called. +// ------------------------------------------------------------------------------- +- (void)mouseExited:(NSEvent*)event +{ + // which tracking area is being tracked? + hoverTag = NSNotFound; + trackEntered = NO; + + [self setNeedsDisplay:YES]; // force update the currently tracked tag to a lighter color +} + +- (void)rightMouseUp:(NSEvent *)theEvent +{ + [self mouseUp:theEvent]; +} + +// ------------------------------------------------------------------------------- +// mouseDown:event +// ------------------------------------------------------------------------------- +- (void)mouseUp:(NSEvent*)event +{ + NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; + + // figure out which tag color was clicked on at mouseUp time + NSInteger index; + for (index = kTrackingAreaNone; index <= kTrackingArea6; index++) + { + NSRect tagRect = [self rectForColorViewAtIndex:index]; + if (NSPointInRect(mousePoint, tagRect)) + { + if(index == selectedTag) //ignore non-changes + return; + + [self setSelectedTag:index]; + + if(observer != nil) { + [observer setValue:[NSNumber numberWithInteger:index] forKeyPath:observerKeyPath]; + } + + if(delegate != nil && [delegate respondsToSelector:@selector(colorSelectorDidChange:)]) { + [delegate colorSelectorDidChange:self]; + } + + [self setNeedsDisplay:YES]; + return; + } + } +} + + + + +@end diff --git a/Source/SPConnectionController.h b/Source/SPConnectionController.h index 5866c495..eb4f0b5c 100644 --- a/Source/SPConnectionController.h +++ b/Source/SPConnectionController.h @@ -44,7 +44,8 @@ #ifndef SP_CODA /* class decl */ ,SPKeychain, SPFavoriteNode, - SPFavoriteTextFieldCell + SPFavoriteTextFieldCell, + SPColorSelectorView #endif ; @@ -79,6 +80,7 @@ NSString *database; NSString *socket; NSString *port; + NSInteger colorIndex; // SSL details NSInteger useSSL; @@ -133,6 +135,9 @@ IBOutlet NSTextField *standardUserField; IBOutlet NSTextField *socketUserField; IBOutlet NSTextField *sshUserField; + IBOutlet SPColorSelectorView *standardColorField; + IBOutlet SPColorSelectorView *sshColorField; + IBOutlet SPColorSelectorView *socketColorField; IBOutlet NSSecureTextField *standardPasswordField; IBOutlet NSSecureTextField *socketPasswordField; IBOutlet NSSecureTextField *sshPasswordField; @@ -185,6 +190,7 @@ @property (readwrite, retain) NSString *socket; @property (readwrite, retain) NSString *port; @property (readwrite, assign) NSInteger useSSL; +@property (readwrite, assign) NSInteger colorIndex; @property (readwrite, assign) NSInteger sslKeyFileLocationEnabled; @property (readwrite, retain) NSString *sslKeyFileLocation; @property (readwrite, assign) NSInteger sslCertificateFileLocationEnabled; diff --git a/Source/SPConnectionController.m b/Source/SPConnectionController.m index 359e2488..f35f27dc 100644 --- a/Source/SPConnectionController.m +++ b/Source/SPConnectionController.m @@ -52,6 +52,7 @@ #import "SPFavoritesExporter.h" #import "SPFavoritesImporter.h" #import "SPThreadAdditions.h" +#import "SPFavoriteColorSupport.h" #import <SPMySQL/SPMySQL.h> @@ -120,6 +121,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, @synthesize database; @synthesize socket; @synthesize port; +@synthesize colorIndex; @synthesize useSSL; @synthesize sslKeyFileLocationEnabled; @synthesize sslKeyFileLocation; @@ -599,6 +601,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, [self setHost:([fav objectForKey:SPFavoriteHostKey] ? [fav objectForKey:SPFavoriteHostKey] : @"")]; [self setSocket:([fav objectForKey:SPFavoriteSocketKey] ? [fav objectForKey:SPFavoriteSocketKey] : @"")]; [self setUser:([fav objectForKey:SPFavoriteUserKey] ? [fav objectForKey:SPFavoriteUserKey] : @"")]; + [self setColorIndex:([fav objectForKey:SPFavoriteColorIndexKey]? [[fav objectForKey:SPFavoriteColorIndexKey] integerValue] : -1)]; [self setPort:([fav objectForKey:SPFavoritePortKey] ? [fav objectForKey:SPFavoritePortKey] : @"")]; [self setDatabase:([fav objectForKey:SPFavoriteDatabaseKey] ? [fav objectForKey:SPFavoriteDatabaseKey] : @"")]; @@ -746,20 +749,34 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, { NSNumber *favoriteID = [self _createNewFavoriteID]; - NSArray *objects = [NSArray arrayWithObjects:NSLocalizedString(@"New Favorite", @"new favorite name"), - [NSNumber numberWithInteger:0], @"", @"", @"", @"", + NSArray *objects = [NSArray arrayWithObjects: + NSLocalizedString(@"New Favorite", @"new favorite name"), + [NSNumber numberWithInteger:0], + @"", + @"", + @"", + [NSNumber numberWithInteger:-1], + @"", [NSNumber numberWithInt:NSOffState], [NSNumber numberWithInt:NSOffState], [NSNumber numberWithInt:NSOffState], - [NSNumber numberWithInt:NSOffState], @"", @"", @"", - [NSNumber numberWithInt:NSOffState], @"", @"", favoriteID, nil]; + [NSNumber numberWithInt:NSOffState], + @"", + @"", + @"", + [NSNumber numberWithInt:NSOffState], + @"", + @"", + favoriteID, + nil]; NSArray *keys = [NSArray arrayWithObjects: SPFavoriteNameKey, SPFavoriteTypeKey, SPFavoriteHostKey, SPFavoriteSocketKey, - SPFavoriteUserKey, + SPFavoriteUserKey, + SPFavoriteColorIndexKey, SPFavoritePortKey, SPFavoriteUseSSLKey, SPFavoriteSSLKeyFileLocationEnabledKey, @@ -1210,7 +1227,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, } else { [theFavorite removeObjectForKey:SPFavoriteDatabaseKey]; } - + [theFavorite setObject:[NSNumber numberWithInteger:[self colorIndex]] forKey:SPFavoriteColorIndexKey]; // SSL details [theFavorite setObject:[NSNumber numberWithInteger:[self useSSL]] forKey:SPFavoriteUseSSLKey]; [theFavorite setObject:[NSNumber numberWithInteger:[self sslKeyFileLocationEnabled]] forKey:SPFavoriteSSLKeyFileLocationEnabledKey]; @@ -1616,6 +1633,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, // Reset the window title [[dbDocument parentWindow] setTitle:[dbDocument displayName]]; [[dbDocument parentTabViewItem] setLabel:[dbDocument displayName]]; + [[dbDocument parentTabViewItem] setColor:nil]; // Stop the current tab's progress indicator [dbDocument setIsProcessing:NO]; @@ -1879,6 +1897,7 @@ static NSComparisonResult _compareFavoritesUsingKey(id favorite1, id favorite2, [self removeObserver:self forKeyPath:SPFavoriteNameKey]; [self removeObserver:self forKeyPath:SPFavoriteHostKey]; [self removeObserver:self forKeyPath:SPFavoriteUserKey]; + [self removeObserver:self forKeyPath:SPFavoriteColorIndexKey]; [self removeObserver:self forKeyPath:SPFavoriteDatabaseKey]; [self removeObserver:self forKeyPath:SPFavoriteSocketKey]; [self removeObserver:self forKeyPath:SPFavoritePortKey]; diff --git a/Source/SPConnectionControllerDelegate.m b/Source/SPConnectionControllerDelegate.m index 9c9d53ca..ce6ab131 100644 --- a/Source/SPConnectionControllerDelegate.m +++ b/Source/SPConnectionControllerDelegate.m @@ -539,6 +539,14 @@ static NSString *SPQuickConnectImageWhite = @"quick-connect-icon-white.pdf"; #endif #pragma mark - +#pragma mark Color Selector delegate + +- (void)colorSelectorDidChange:(SPColorSelectorView *)sel +{ + [self _startEditingConnection]; +} + +#pragma mark - #pragma mark Scroll view notifications #ifndef SP_CODA diff --git a/Source/SPConnectionControllerInitializer.m b/Source/SPConnectionControllerInitializer.m index 7ea615e5..b46e9986 100644 --- a/Source/SPConnectionControllerInitializer.m +++ b/Source/SPConnectionControllerInitializer.m @@ -39,6 +39,8 @@ #import "SPGroupNode.h" #import "SPDatabaseViewController.h" #import "SPSplitView.h" +#import "SPFavoriteColorSupport.h" +#import "SPColorSelectorView.h" #ifndef SP_CODA static NSString *SPConnectionViewNibName = @"ConnectionView"; @@ -99,6 +101,15 @@ static NSString *SPConnectionViewNibName = @"ConnectionView"; favoriteNameFieldWasAutogenerated = NO; [self loadNib]; + + NSArray *colorList = [[SPFavoriteColorSupport sharedInstance] userColorList]; + [sshColorField setColorList:colorList]; + [sshColorField bind:@"selectedTag" toObject:self withKeyPath:@"colorIndex" options:nil]; + [standardColorField setColorList:colorList]; + [standardColorField bind:@"selectedTag" toObject:self withKeyPath:@"colorIndex" options:nil]; + [socketColorField setColorList:colorList]; + [socketColorField bind:@"selectedTag" toObject:self withKeyPath:@"colorIndex" options:nil]; + [self registerForNotifications]; #ifndef SP_CODA @@ -219,6 +230,11 @@ static NSString *SPConnectionViewNibName = @"ConnectionView"; options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) context:NULL]; + [self addObserver:self + forKeyPath:SPFavoriteColorIndexKey + options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) + context:NULL]; + [self addObserver:self forKeyPath:SPFavoriteDatabaseKey options:(NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew) diff --git a/Source/SPConstants.h b/Source/SPConstants.h index b353b2dc..872ad0f5 100644 --- a/Source/SPConstants.h +++ b/Source/SPConstants.h @@ -371,6 +371,7 @@ extern NSString *SPFavoritesSortedBy; extern NSString *SPFavoritesSortedInReverse; extern NSString *SPAlwaysShowWindowTabBar; extern NSString *SPResetAutoIncrementAfterDeletionOfAllRows; +extern NSString *SPFavoriteColorList; // Hidden Prefs extern NSString *SPPrintWarningRowLimit; @@ -463,6 +464,7 @@ extern NSString *SPFavoriteDatabaseKey; extern NSString *SPFavoriteHostKey; extern NSString *SPFavoritePortKey; extern NSString *SPFavoriteUserKey; +extern NSString *SPFavoriteColorIndexKey; extern NSString *SPFavoriteTypeKey; extern NSString *SPFavoriteSocketKey; extern NSString *SPFavoriteSSHHostKey; diff --git a/Source/SPConstants.m b/Source/SPConstants.m index a5683cbf..d257e5dd 100644 --- a/Source/SPConstants.m +++ b/Source/SPConstants.m @@ -177,6 +177,7 @@ NSString *SPFavoritesSortedBy = @"FavoritesSortedBy"; NSString *SPFavoritesSortedInReverse = @"FavoritesSortedInReverse"; NSString *SPAlwaysShowWindowTabBar = @"WindowAlwaysShowTabBar"; NSString *SPResetAutoIncrementAfterDeletionOfAllRows = @"ResetAutoIncrementAfterDeletionOfAllRows"; +NSString *SPFavoriteColorList = @"FavoriteColorList"; // Hidden Prefs NSString *SPPrintWarningRowLimit = @"PrintWarningRowLimit"; @@ -279,6 +280,7 @@ NSString *SPFavoriteDatabaseKey = @"database"; NSString *SPFavoriteHostKey = @"host"; NSString *SPFavoritePortKey = @"port"; NSString *SPFavoriteUserKey = @"user"; +NSString *SPFavoriteColorIndexKey = @"colorIndex"; NSString *SPFavoriteTypeKey = @"type"; NSString *SPFavoriteSocketKey = @"socket"; NSString *SPFavoriteSSHHostKey = @"sshHost"; diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index 85246443..0993458b 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -101,6 +101,7 @@ enum { #import "SPThreadAdditions.h" #import "RegexKitLite.h" #import "SPTextView.h" +#import "SPFavoriteColorSupport.h" #ifdef SP_CODA /* headers */ #import "SPAlertSheets.h" @@ -3727,6 +3728,8 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; NSMutableString *tabTitle; NSMutableString *windowTitle; SPDatabaseDocument *frontTableDocument = [parentWindowController selectedTableDocument]; + + NSColor *tabColor = nil; // Determine name details NSString *pathName = @""; @@ -3743,6 +3746,8 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; tabTitle = windowTitle; } else { + tabColor = [[SPFavoriteColorSupport sharedInstance] colorForIndex:[connectionController colorIndex]]; + windowTitle = [NSMutableString string]; tabTitle = [NSMutableString string]; @@ -3784,6 +3789,7 @@ static NSString *SPAlterDatabaseAction = @"SPAlterDatabase"; // Set the titles [parentTabViewItem setLabel:tabTitle]; + [parentTabViewItem setColor:tabColor]; if ([parentWindowController selectedTableDocument] == self) { [parentWindow setTitle:windowTitle]; } diff --git a/Source/SPFavoriteColorSupport.h b/Source/SPFavoriteColorSupport.h new file mode 100644 index 00000000..ad35b80d --- /dev/null +++ b/Source/SPFavoriteColorSupport.h @@ -0,0 +1,61 @@ +// +// $Id$ +// +// SPFavoriteColorSupport.h +// sequel-pro +// +// Created by Max Lohrmann on 2013-10-20 +// Copyright (c) 2013 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 <http://code.google.com/p/sequel-pro/> + +#import <Foundation/Foundation.h> + +@interface SPFavoriteColorSupport : NSObject { + NSUserDefaults *prefs; +} + +/** + * Get the single instance of this class + */ ++ (SPFavoriteColorSupport *)sharedInstance; + +/** + * Get the default list of colors supplied by Sequel Pro. + * @return An array with NSColor * items. + */ ++ (NSArray *)defaultColorList; + +/** + * Get the current color for a specific index. + * @return The color or nil if colorIndex was < 0 or the index was not defined. + */ +- (NSColor *)colorForIndex:(NSInteger)colorIndex; + +/** + * The current list of colors from user prefs. + * @return An array with NSColor * items. + */ +- (NSArray *)userColorList; +@end diff --git a/Source/SPFavoriteColorSupport.m b/Source/SPFavoriteColorSupport.m new file mode 100644 index 00000000..10519791 --- /dev/null +++ b/Source/SPFavoriteColorSupport.m @@ -0,0 +1,96 @@ +// +// $Id$ +// +// SPFavoriteColorSupport.m +// sequel-pro +// +// Created by Max Lohrmann on 2013-10-20 +// Copyright (c) 2013 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 <http://code.google.com/p/sequel-pro/> + +#import "SPFavoriteColorSupport.h" + +@implementation SPFavoriteColorSupport + +static SPFavoriteColorSupport *ColorSupport = nil; + +- (id)init +{ + self = [super init]; + if (self) { + prefs = [NSUserDefaults standardUserDefaults]; + } + return self; +} + ++ (SPFavoriteColorSupport *)sharedInstance +{ + if(!ColorSupport) + ColorSupport = [[self allocWithZone:NULL] init]; + + return ColorSupport; +} + + ++ (NSArray *)defaultColorList +{ + return [NSArray arrayWithObjects: + [NSColor colorWithDeviceRed:228.0/255.0 green:116.0/255.0 blue:102.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:237.0/255.0 green:174.0/255.0 blue:107.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:227.0/255.0 green:213.0/255.0 blue:119.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:175.0/255.0 green:215.0/255.0 blue:119.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:118.0/255.0 green:185.0/255.0 blue:232.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:202.0/255.0 green:152.0/255.0 blue:224.0/255.0 alpha:1.0], + [NSColor colorWithDeviceRed:182.0/255.0 green:182.0/255.0 blue:182.0/255.0 alpha:1.0], + nil]; +} + + +- (NSColor *)colorForIndex:(NSInteger)colorIndex +{ + NSArray *colorList = [self userColorList]; + //check bounds + if(colorIndex < 0 || (NSUInteger)colorIndex >= [colorList count]) { + NSLog(@"%s: Requesting color index %ld, but only have %lu items. Returning nil.",__PRETTY_FUNCTION__,(long)colorIndex,(unsigned long)[colorList count]); + return nil; + } + + return [colorList objectAtIndex:colorIndex]; +} + + +- (NSArray *)userColorList +{ + NSArray *archivedColors = [prefs objectForKey:SPFavoriteColorList]; + NSMutableArray *colorList = [NSMutableArray arrayWithCapacity:[archivedColors count]]; + for (NSData *archivedColor in archivedColors) { + NSColor *color = [NSUnarchiver unarchiveObjectWithData:archivedColor]; + [colorList addObject:color]; + } + + return [[colorList copy] autorelease]; +} + +@end diff --git a/Source/SPWindowController.m b/Source/SPWindowController.m index aa208286..2d1f5058 100644 --- a/Source/SPWindowController.m +++ b/Source/SPWindowController.m @@ -110,6 +110,7 @@ enum { // Set up a new tab with the connection view as the identifier, add the view, and add it to the tab view NSTabViewItem *newItem = [[[NSTabViewItem alloc] initWithIdentifier:newTableDocument] autorelease]; + [newItem setColor:nil]; //cocoa defaults to [NSColor controlColor] but we want the tabstyle to choose a default color [newItem setView:[newTableDocument databaseView]]; [tabView addTabViewItem:newItem]; |