aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/SPColorSelectorView.h81
-rw-r--r--Source/SPColorSelectorView.m436
-rw-r--r--Source/SPConnectionController.h8
-rw-r--r--Source/SPConnectionController.m31
-rw-r--r--Source/SPConnectionControllerDelegate.m8
-rw-r--r--Source/SPConnectionControllerInitializer.m16
-rw-r--r--Source/SPConstants.h2
-rw-r--r--Source/SPConstants.m2
-rw-r--r--Source/SPDatabaseDocument.m6
-rw-r--r--Source/SPFavoriteColorSupport.h61
-rw-r--r--Source/SPFavoriteColorSupport.m96
-rw-r--r--Source/SPWindowController.m1
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];