From 8bb33b515e95606566e8286b5714e7e3be01ffad Mon Sep 17 00:00:00 2001 From: avenjamin Date: Mon, 14 Jun 2010 15:22:43 +0000 Subject: Initial stage of re styling the tab bar to actually look half decent. - Change line 373 of PSMTabBarControl to "SequelPro" to see new tabs. - The drawing of the tab edges needs to be redone on the very edge of each tab instead of being inset by a number pixels to resolve a few issues. --- Frameworks/PSMTabBar/Images/AddTabButton.png | Bin 0 -> 1063 bytes Frameworks/PSMTabBar/Images/AddTabButtonPushed.png | Bin 0 -> 1038 bytes .../PSMTabBar/Images/AddTabButtonRollover.png | Bin 0 -> 1047 bytes Frameworks/PSMTabBar/PSMTabBarControl.m | 41 +- Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h | 52 ++ Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m | 682 +++++++++++++++++++++ Interfaces/English.lproj/MainWindow.xib | 86 ++- Source/SPDatabaseDocument.m | 1 + Source/SPWindowController.m | 2 +- sequel-pro.xcodeproj/project.pbxproj | 20 + 10 files changed, 863 insertions(+), 21 deletions(-) create mode 100644 Frameworks/PSMTabBar/Images/AddTabButton.png create mode 100644 Frameworks/PSMTabBar/Images/AddTabButtonPushed.png create mode 100644 Frameworks/PSMTabBar/Images/AddTabButtonRollover.png create mode 100644 Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h create mode 100644 Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m diff --git a/Frameworks/PSMTabBar/Images/AddTabButton.png b/Frameworks/PSMTabBar/Images/AddTabButton.png new file mode 100644 index 00000000..0ed2bc26 Binary files /dev/null and b/Frameworks/PSMTabBar/Images/AddTabButton.png differ diff --git a/Frameworks/PSMTabBar/Images/AddTabButtonPushed.png b/Frameworks/PSMTabBar/Images/AddTabButtonPushed.png new file mode 100644 index 00000000..9f370a0d Binary files /dev/null and b/Frameworks/PSMTabBar/Images/AddTabButtonPushed.png differ diff --git a/Frameworks/PSMTabBar/Images/AddTabButtonRollover.png b/Frameworks/PSMTabBar/Images/AddTabButtonRollover.png new file mode 100644 index 00000000..6138f3ed Binary files /dev/null and b/Frameworks/PSMTabBar/Images/AddTabButtonRollover.png differ diff --git a/Frameworks/PSMTabBar/PSMTabBarControl.m b/Frameworks/PSMTabBar/PSMTabBarControl.m index 9242f8a1..5b72f1e6 100644 --- a/Frameworks/PSMTabBar/PSMTabBarControl.m +++ b/Frameworks/PSMTabBar/PSMTabBarControl.m @@ -16,6 +16,7 @@ #import "PSMUnifiedTabStyle.h" #import "PSMCardTabStyle.h" #import "PSMAdiumTabStyle.h" +#import "PSMSequelProTabStyle.h" #import "PSMTabDragAssistant.h" #import "PSMTabBarController.h" @@ -367,22 +368,32 @@ - (void)setStyleNamed:(NSString *)name { id newStyle; -/* - if ([name isEqualToString:@"Aqua"]) { - newStyle = [[PSMAquaTabStyle alloc] init]; - } else if ([name isEqualToString:@"Unified"]) { - newStyle = [[PSMUnifiedTabStyle alloc] init]; - } else if ([name isEqualToString:@"Adium"]) { - newStyle = [[PSMAdiumTabStyle alloc] init]; + + // Hardcode style to Metal + name = @"Metal"; + + if ([name isEqualToString:@"Aqua"]) { + //newStyle = [[PSMAquaTabStyle alloc] init]; + + } else if ([name isEqualToString:@"Unified"]) { + //newStyle = [[PSMUnifiedTabStyle alloc] init]; + + } else if ([name isEqualToString:@"Adium"]) { + //newStyle = [[PSMAdiumTabStyle alloc] init]; + } else if ([name isEqualToString:@"Card"]) { - newStyle = [[PSMCardTabStyle alloc] init]; - } else { -*/ - newStyle = [[PSMMetalTabStyle alloc] init]; -/* - } -*/ - + //newStyle = [[PSMCardTabStyle alloc] init]; + + } else if ([name isEqualToString:@"Metal"]) { + newStyle = [[PSMMetalTabStyle alloc] init]; + + } else if ([name isEqualToString:@"SequelPro"]) { + newStyle = [[PSMSequelProTabStyle alloc] init]; + + } else { + newStyle = [[PSMMetalTabStyle alloc] init]; + } + [self setStyle:newStyle]; [newStyle release]; } diff --git a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h new file mode 100644 index 00000000..4015ed8e --- /dev/null +++ b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.h @@ -0,0 +1,52 @@ +// +// $Id: PSMSequelProTabStyle.h 2317 2010-06-15 10:19:41Z avenjamin $ +// +// PSMSequelProTabStyle.h +// sequel-pro +// +// Created by Ben Perry on June 15, 2010 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import +#import "PSMTabStyle.h" + +@interface PSMSequelProTabStyle : NSObject { + NSImage *metalCloseButton; + NSImage *metalCloseButtonDown; + NSImage *metalCloseButtonOver; + NSImage *metalCloseDirtyButton; + NSImage *metalCloseDirtyButtonDown; + NSImage *metalCloseDirtyButtonOver; + NSImage *_addTabButtonImage; + NSImage *_addTabButtonPressedImage; + NSImage *_addTabButtonRolloverImage; + + NSDictionary *_objectCountStringAttributes; + + PSMTabBarOrientation orientation; + PSMTabBarControl *tabBar; + + BOOL _tabIsRightOfSelectedTab; +} + +- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView; + +- (void)encodeWithCoder:(NSCoder *)aCoder; +- (id)initWithCoder:(NSCoder *)aDecoder; + +@end diff --git a/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m new file mode 100644 index 00000000..7e58930a --- /dev/null +++ b/Frameworks/PSMTabBar/Styles/PSMSequelProTabStyle.m @@ -0,0 +1,682 @@ +// +// $Id: PSMSequelProTabStyle.m 2317 2010-06-15 10:19:41Z avenjamin $ +// +// PSMSequelProTabStyle.m +// sequel-pro +// +// Created by Ben Perry on June 15, 2010 +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// More info at + +#import "PSMSequelProTabStyle.h" +#import "PSMTabBarCell.h" +#import "PSMTabBarControl.h" +#import "NSBezierPath_AMShading.h" + +#define kPSMMetalObjectCounterRadius 7.0 +#define kPSMMetalCounterMinWidth 20 +#define kPSMMetalTabCornerRadius 4.5 +#define MARGIN_X 10 + +@implementation PSMSequelProTabStyle + +- (NSString *)name +{ + return @"SequelPro"; +} + +#pragma mark - +#pragma mark Creation/Destruction + +- (id) init +{ + if ( (self = [super init]) ) { + metalCloseButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Front"]]; + metalCloseButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Front_Pressed"]]; + metalCloseButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Front_Rollover"]]; + + metalCloseDirtyButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Dirty"]]; + metalCloseDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Dirty_Pressed"]]; + metalCloseDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabClose_Dirty_Rollover"]]; + + _addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AddTabButton"]]; + _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AddTabButtonPushed"]]; + _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AddTabButtonRollover"]]; + + _objectCountStringAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSFontManager sharedFontManager] convertFont:[NSFont fontWithName:@"Helvetica" size:11.0] toHaveTrait:NSBoldFontMask], NSFontAttributeName, + [[NSColor whiteColor] colorWithAlphaComponent:0.85], NSForegroundColorAttributeName, + nil, nil]; + } + return self; +} + +- (void)dealloc +{ + [metalCloseButton release]; + [metalCloseButtonDown release]; + [metalCloseButtonOver release]; + [metalCloseDirtyButton release]; + [metalCloseDirtyButtonDown release]; + [metalCloseDirtyButtonOver release]; + [_addTabButtonImage release]; + [_addTabButtonPressedImage release]; + [_addTabButtonRolloverImage release]; + + [_objectCountStringAttributes release]; + + [super dealloc]; +} + +#pragma mark - +#pragma mark Control Specific + +- (CGFloat)leftMarginForTabBarControl +{ + return 0.0f; +} + +- (CGFloat)rightMarginForTabBarControl +{ + return 0.0f; +} + +- (CGFloat)topMarginForTabBarControl +{ + return 10.0f; +} + +- (void)setOrientation:(PSMTabBarOrientation)value +{ + // Hard code orientation to horizontal + orientation = PSMTabBarHorizontalOrientation; +} + +#pragma mark - +#pragma mark Add Tab Button + +- (NSImage *)addTabButtonImage +{ + return _addTabButtonImage; +} + +- (NSImage *)addTabButtonPressedImage +{ + return _addTabButtonPressedImage; +} + +- (NSImage *)addTabButtonRolloverImage +{ + return _addTabButtonRolloverImage; +} + +#pragma mark - +#pragma mark Cell Specific + +- (NSRect)dragRectForTabCell:(PSMTabBarCell *)cell orientation:(PSMTabBarOrientation)tabOrientation +{ + NSRect dragRect = [cell frame]; + dragRect.size.width++; + + if ([cell tabState] & PSMTab_SelectedMask) { + if (tabOrientation == PSMTabBarHorizontalOrientation) { + dragRect.size.height -= 2.0; + } else { + dragRect.size.height += 1.0; + dragRect.origin.y -= 1.0; + dragRect.origin.x += 2.0; + dragRect.size.width -= 3.0; + } + } else if (tabOrientation == PSMTabBarVerticalOrientation) { + dragRect.origin.x--; + } + + return dragRect; +} + +- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame +{ + if ([cell hasCloseButton] == NO) { + return NSZeroRect; + } + + NSRect result; + result.size = [metalCloseButton size]; + result.origin.x = cellFrame.origin.x + MARGIN_X; + result.origin.y = cellFrame.origin.y + MARGIN_Y + 2.0; + + return result; +} + +- (NSRect)iconRectForTabCell:(PSMTabBarCell *)cell +{ + NSRect cellFrame = [cell frame]; + + if ([cell hasIcon] == NO) { + return NSZeroRect; + } + + NSRect result; + result.size = NSMakeSize(kPSMTabBarIconWidth, kPSMTabBarIconWidth); + result.origin.x = cellFrame.origin.x + MARGIN_X; + result.origin.y = cellFrame.origin.y + MARGIN_Y; + + if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { + result.origin.x += [metalCloseButton size].width + kPSMTabBarCellPadding; + } + + return result; +} + +- (NSRect)indicatorRectForTabCell:(PSMTabBarCell *)cell +{ + NSRect cellFrame = [cell frame]; + + if ([[cell indicator] isHidden]) { + return NSZeroRect; + } + + NSRect result; + result.size = NSMakeSize(kPSMTabBarIndicatorWidth, kPSMTabBarIndicatorWidth); + result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - kPSMTabBarIndicatorWidth; + result.origin.y = cellFrame.origin.y + MARGIN_Y; + + return result; +} + +- (NSRect)objectCounterRectForTabCell:(PSMTabBarCell *)cell +{ + NSRect cellFrame = [cell frame]; + + if ([cell count] == 0) { + return NSZeroRect; + } + + CGFloat countWidth = [[self attributedObjectCountValueForTabCell:cell] size].width; + countWidth += (2 * kPSMMetalObjectCounterRadius - 6.0); + if (countWidth < kPSMMetalCounterMinWidth) { + countWidth = kPSMMetalCounterMinWidth; + } + + NSRect result; + result.size = NSMakeSize(countWidth, 2 * kPSMMetalObjectCounterRadius); // temp + result.origin.x = cellFrame.origin.x + cellFrame.size.width - MARGIN_X - result.size.width; + result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0; + + if (![[cell indicator] isHidden]) { + result.origin.x -= kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding; + } + + return result; +} + + +- (CGFloat)minimumWidthOfTabCell:(PSMTabBarCell *)cell +{ + CGFloat resultWidth = 0.0; + + // left margin + resultWidth = MARGIN_X; + + // close button? + if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { + resultWidth += [metalCloseButton size].width + kPSMTabBarCellPadding; + } + + // icon? + if ([cell hasIcon]) { + resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding; + } + + // the label + resultWidth += kPSMMinimumTitleWidth; + + // object counter? + if ([cell count] > 0) { + resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding; + } + + // indicator? + if ([[cell indicator] isHidden] == NO) + resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth; + + // right margin + resultWidth += MARGIN_X; + + return ceil(resultWidth); +} + +- (CGFloat)desiredWidthOfTabCell:(PSMTabBarCell *)cell +{ + CGFloat resultWidth = 0.0; + + // left margin + resultWidth = MARGIN_X; + + // close button? + if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) + resultWidth += [metalCloseButton size].width + kPSMTabBarCellPadding; + + // icon? + if ([cell hasIcon]) { + resultWidth += kPSMTabBarIconWidth + kPSMTabBarCellPadding; + } + + // the label + resultWidth += [[cell attributedStringValue] size].width; + + // object counter? + if ([cell count] > 0) { + resultWidth += [self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding; + } + + // indicator? + if ([[cell indicator] isHidden] == NO) + resultWidth += kPSMTabBarCellPadding + kPSMTabBarIndicatorWidth; + + // right margin + resultWidth += MARGIN_X; + + return ceil(resultWidth); +} + +- (CGFloat)tabCellHeight +{ + return kPSMTabBarControlHeight; +} + +#pragma mark - +#pragma mark Cell Values + +- (NSAttributedString *)attributedObjectCountValueForTabCell:(PSMTabBarCell *)cell +{ + NSString *contents = [NSString stringWithFormat:@"%lu", (unsigned long)[cell count]]; + return [[[NSMutableAttributedString alloc] initWithString:contents attributes:_objectCountStringAttributes] autorelease]; +} + +- (NSAttributedString *)attributedStringValueForTabCell:(PSMTabBarCell *)cell +{ + NSMutableAttributedString *attrStr; + NSString *contents = [cell stringValue]; + attrStr = [[[NSMutableAttributedString alloc] initWithString:contents] autorelease]; + NSRange range = NSMakeRange(0, [contents length]); + + // Add font attribute + [attrStr addAttribute:NSFontAttributeName value:[NSFont boldSystemFontOfSize:11.0] range:range]; + [attrStr addAttribute:NSForegroundColorAttributeName value:[[NSColor textColor] colorWithAlphaComponent:0.75] range:range]; + + // Add shadow attribute + NSShadow* shadow; + shadow = [[[NSShadow alloc] init] autorelease]; + CGFloat shadowAlpha; + if (([cell state] == NSOnState) || [cell isHighlighted]) { + shadowAlpha = 0.8; + } else { + shadowAlpha = 0.5; + } + [shadow setShadowColor:[NSColor colorWithCalibratedWhite:1.0 alpha:shadowAlpha]]; + [shadow setShadowOffset:NSMakeSize(0, -1)]; + [shadow setShadowBlurRadius:1.0]; + [attrStr addAttribute:NSShadowAttributeName value:shadow range:range]; + + // Paragraph Style for Truncating Long Text + static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil; + if (!TruncatingTailParagraphStyle) { + TruncatingTailParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain]; + [TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingTail]; + [TruncatingTailParagraphStyle setAlignment:NSCenterTextAlignment]; + } + [attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range]; + + return attrStr; +} + +#pragma mark - +#pragma mark ---- drawing ---- + +// Step 1 +- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect +{ + if (orientation != [bar orientation]) { + orientation = [bar orientation]; + } + + if (tabBar != bar) { + tabBar = bar; + } + + [self drawBackgroundInRect:rect]; + + // no tab view == not connected + if (![bar tabView]) { + NSRect labelRect = rect; + labelRect.size.height -= 4.0; + labelRect.origin.y += 4.0; + NSMutableAttributedString *attrStr; + NSString *contents = @"PSMTabBarControl"; + attrStr = [[[NSMutableAttributedString alloc] initWithString:contents] autorelease]; + NSRange range = NSMakeRange(0, [contents length]); + [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] range:range]; + NSMutableParagraphStyle *centeredParagraphStyle = nil; + + if (!centeredParagraphStyle) { + centeredParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain]; + [centeredParagraphStyle setAlignment:NSCenterTextAlignment]; + } + [attrStr addAttribute:NSParagraphStyleAttributeName value:centeredParagraphStyle range:range]; + [attrStr drawInRect:labelRect]; + return; + } + + // draw cells + NSEnumerator *e = [[bar cells] objectEnumerator]; + PSMTabBarCell *cell; + _tabIsRightOfSelectedTab = NO; + while ( (cell = [e nextObject]) ) { + if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) { + [cell drawWithFrame:[cell frame] inView:bar]; + } + } + _tabIsRightOfSelectedTab = NO; +} + + +// Step 2 +- (void)drawBackgroundInRect:(NSRect)rect +{ + //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area + rect = [tabBar bounds]; + + [NSGraphicsContext saveGraphicsState]; + [[NSGraphicsContext currentContext] setShouldAntialias:NO]; + + + if ([[tabBar window] isKeyWindow]) { + + // fill in background of tab bar + [[NSColor colorWithCalibratedWhite:0.495 alpha:1.0] set]; + NSRectFillUsingOperation(rect, NSCompositeSourceAtop); + + // draw horizontal line across top and bottom edge + [[NSColor darkGrayColor] set]; + [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + 0.5) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + 0.5)]; + [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height - 0.5) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - 0.5)]; + + } else { + + // fill in background of tab bar + [[NSColor colorWithCalibratedWhite:0.685 alpha:1.0] set]; + NSRectFillUsingOperation(rect, NSCompositeSourceAtop); + + // draw horizontal line across top and bottom edge + [[NSColor colorWithCalibratedWhite:0.49 alpha:1.0] set]; + [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + 0.5) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + 0.5)]; + [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height - 0.5) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height - 0.5)]; + } + + + [NSGraphicsContext restoreGraphicsState]; +} + + + +// Step 3 +- (void)drawTabCell:(PSMTabBarCell *)cell +{ + NSRect cellFrame = [cell frame]; + NSColor *lineColor = nil; + NSBezierPath *bezier = [NSBezierPath bezierPath]; + NSPoint center = NSZeroPoint; + + if ([[tabBar window] isKeyWindow]) { + lineColor = [NSColor darkGrayColor]; + } else { + lineColor = [NSColor colorWithCalibratedWhite:0.49 alpha:1.0]; + } + + //disable antialiasing of bezier paths + [NSGraphicsContext saveGraphicsState]; + [[NSGraphicsContext currentContext] setShouldAntialias:YES]; + + + NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height); + + // selected tab + if ([cell state] == NSOnState) { + + // draw top left arc + center = NSMakePoint(aRect.origin.x, aRect.origin.y + kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:270 endAngle:360 clockwise:NO]; + + // draw bottom left arc + center = NSMakePoint(aRect.origin.x + (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + + // draw bottom right arc + center = NSMakePoint(aRect.origin.x + aRect.size.width - (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; + + // draw top right arc + center = NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:180 endAngle:270 clockwise:NO]; + + + if ([[tabBar window] isKeyWindow]) { + [[NSColor colorWithCalibratedWhite:0.59 alpha:1.0] set]; + } else { + [[NSColor colorWithCalibratedWhite:0.81 alpha:1.0] set]; + } + + [bezier fill]; + + [bezier moveToPoint:NSMakePoint(aRect.origin.x + (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - 0.5)]; + [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width - (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - 0.5)]; + + // Yeah..um..right right? + _tabIsRightOfSelectedTab = YES; + + // unselected tab + } else { + + // rollover +// if ([cell isHighlighted]) { +// [[NSColor colorWithCalibratedWhite:1.0 alpha:0.1] set]; +// NSRectFillUsingOperation(aRect, NSCompositeSourceAtop); +// } + + if (_tabIsRightOfSelectedTab) { + //lineColor = [NSColor greenColor]; + + // draw bottom right arc + center = NSMakePoint(aRect.origin.x + aRect.size.width - (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:90 endAngle:0 clockwise:YES]; + + // draw top right arc + center = NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:180 endAngle:270 clockwise:NO]; + + } else { + //lineColor = [NSColor redColor]; + + // draw top left arc + center = NSMakePoint(aRect.origin.x, aRect.origin.y + kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:270 endAngle:360 clockwise:NO]; + + // draw bottom left arc + center = NSMakePoint(aRect.origin.x + (2 * kPSMMetalTabCornerRadius), aRect.origin.y + aRect.size.height - kPSMMetalTabCornerRadius); + [bezier appendBezierPathWithArcWithCenter:center radius:kPSMMetalTabCornerRadius startAngle:180 endAngle:90 clockwise:YES]; + } + } + + [lineColor set]; + [bezier stroke]; + + + [NSGraphicsContext restoreGraphicsState]; + + [self drawInteriorWithTabCell:cell inView:[cell controlView]]; +} + + +// Step 4 +- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView +{ + NSRect cellFrame = [cell frame]; + CGFloat labelPosition = cellFrame.origin.x + MARGIN_X; + + // close button + if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed] && [cell isHighlighted]) { + + NSSize closeButtonSize = NSZeroSize; + NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame]; + NSImage * closeButton = nil; + + if ([cell state] != NSOnState & _tabIsRightOfSelectedTab) { + closeButtonRect.origin.x -= MARGIN_X; + } + + closeButton = [cell isEdited] ? metalCloseDirtyButton : metalCloseButton; + + if ([cell closeButtonOver]) closeButton = [cell isEdited] ? metalCloseDirtyButtonOver : metalCloseButtonOver; + if ([cell closeButtonPressed]) closeButton = [cell isEdited] ? metalCloseDirtyButtonDown : metalCloseButtonDown; + + closeButtonSize = [closeButton size]; + + if ([controlView isFlipped]) { + closeButtonRect.origin.y += closeButtonRect.size.height; + } + + [closeButton compositeToPoint:closeButtonRect.origin operation:NSCompositeSourceOver fraction:1.0]; + + // scoot label over + //labelPosition += closeButtonSize.width + kPSMTabBarCellPadding; + } + + // icon + if ([cell hasIcon]) { + NSRect iconRect = [self iconRectForTabCell:cell]; + NSImage *icon = [[[cell representedObject] identifier] icon]; + + if ([controlView isFlipped]) { + iconRect.origin.y += iconRect.size.height; + } + + // center in available space (in case icon image is smaller than kPSMTabBarIconWidth) + if ([icon size].width < kPSMTabBarIconWidth) { + iconRect.origin.x += (kPSMTabBarIconWidth - [icon size].width)/2.0; + } + if ([icon size].height < kPSMTabBarIconWidth) { + iconRect.origin.y -= (kPSMTabBarIconWidth - [icon size].height)/2.0; + } + + [icon compositeToPoint:iconRect.origin operation:NSCompositeSourceOver fraction:1.0]; + + // scoot label over + labelPosition += iconRect.size.width + kPSMTabBarCellPadding; + } + + // label rect + NSRect labelRect; + labelRect.origin.x = labelPosition; + labelRect.size.width = cellFrame.size.width - (labelRect.origin.x - cellFrame.origin.x) - kPSMTabBarCellPadding; + labelRect.size.height = cellFrame.size.height; + labelRect.origin.y = cellFrame.origin.y + MARGIN_Y; + + if ([cell state] == NSOnState) { + //labelRect.origin.y -= 1; + } + + if (![[cell indicator] isHidden]) { + labelRect.size.width -= (kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding); + } + + // object counter + if ([cell count] > 0) { + [[cell countColor] ?: [NSColor colorWithCalibratedWhite:0.3 alpha:0.6] set]; + NSBezierPath *path = [NSBezierPath bezierPath]; + NSRect myRect = [self objectCounterRectForTabCell:cell]; + if ([cell state] == NSOnState) { + //myRect.origin.y -= 1.0; + } + [path moveToPoint:NSMakePoint(myRect.origin.x + kPSMMetalObjectCounterRadius, myRect.origin.y)]; + [path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMMetalObjectCounterRadius, myRect.origin.y)]; + [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMMetalObjectCounterRadius, myRect.origin.y + kPSMMetalObjectCounterRadius) radius:kPSMMetalObjectCounterRadius startAngle:270.0 endAngle:90.0]; + [path lineToPoint:NSMakePoint(myRect.origin.x + kPSMMetalObjectCounterRadius, myRect.origin.y + myRect.size.height)]; + [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMMetalObjectCounterRadius, myRect.origin.y + kPSMMetalObjectCounterRadius) radius:kPSMMetalObjectCounterRadius startAngle:90.0 endAngle:270.0]; + [path fill]; + + // draw attributed string centered in area + NSRect counterStringRect; + NSAttributedString *counterString = [self attributedObjectCountValueForTabCell:cell]; + counterStringRect.size = [counterString size]; + counterStringRect.origin.x = myRect.origin.x + ((myRect.size.width - counterStringRect.size.width) / 2.0) + 0.25; + counterStringRect.origin.y = myRect.origin.y + ((myRect.size.height - counterStringRect.size.height) / 2.0) + 0.5; + [counterString drawInRect:counterStringRect]; + + // shrink label width to make room for object counter + labelRect.size.width -= myRect.size.width + kPSMTabBarCellPadding; + } + + // draw label + [[cell attributedStringValue] drawInRect:labelRect]; +} + + + +#pragma mark - +#pragma mark Archiving + +- (void)encodeWithCoder:(NSCoder *)aCoder +{ + //[super encodeWithCoder:aCoder]; +/* + if ([aCoder allowsKeyedCoding]) { + [aCoder encodeObject:metalCloseButton forKey:@"metalCloseButton"]; + [aCoder encodeObject:metalCloseButtonDown forKey:@"metalCloseButtonDown"]; + [aCoder encodeObject:metalCloseButtonOver forKey:@"metalCloseButtonOver"]; + [aCoder encodeObject:metalCloseDirtyButton forKey:@"metalCloseDirtyButton"]; + [aCoder encodeObject:metalCloseDirtyButtonDown forKey:@"metalCloseDirtyButtonDown"]; + [aCoder encodeObject:metalCloseDirtyButtonOver forKey:@"metalCloseDirtyButtonOver"]; + [aCoder encodeObject:_addTabButtonImage forKey:@"addTabButtonImage"]; + [aCoder encodeObject:_addTabButtonPressedImage forKey:@"addTabButtonPressedImage"]; + [aCoder encodeObject:_addTabButtonRolloverImage forKey:@"addTabButtonRolloverImage"]; + } +*/ +} + +- (id)initWithCoder:(NSCoder *)aDecoder +{ + self = [self init]; + if (self) { + +/* + if ([aDecoder allowsKeyedCoding]) { + metalCloseButton = [[aDecoder decodeObjectForKey:@"metalCloseButton"] retain]; + metalCloseButtonDown = [[aDecoder decodeObjectForKey:@"metalCloseButtonDown"] retain]; + metalCloseButtonOver = [[aDecoder decodeObjectForKey:@"metalCloseButtonOver"] retain]; + metalCloseDirtyButton = [[aDecoder decodeObjectForKey:@"metalCloseDirtyButton"] retain]; + metalCloseDirtyButtonDown = [[aDecoder decodeObjectForKey:@"metalCloseDirtyButtonDown"] retain]; + metalCloseDirtyButtonOver = [[aDecoder decodeObjectForKey:@"metalCloseDirtyButtonOver"] retain]; + _addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain]; + _addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain]; + _addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain]; + } +*/ + } + return self; +} + +@end diff --git a/Interfaces/English.lproj/MainWindow.xib b/Interfaces/English.lproj/MainWindow.xib index 8d16f4a2..afd57750 100644 --- a/Interfaces/English.lproj/MainWindow.xib +++ b/Interfaces/English.lproj/MainWindow.xib @@ -12,7 +12,7 @@ YES - + YES @@ -56,14 +56,14 @@ 266 - {{0, 534}, {948, 22}} + {{0, 533}, {948, 22}} PSMTabBarControl 274 - {948, 534} + {948, 533} YES @@ -224,9 +224,9 @@ YES - {{54, 203}, {948, 555}} + {{42, 293}, {948, 555}} com.apple.InterfaceBuilder.CocoaPlugin - {{54, 203}, {948, 555}} + {{42, 293}, {948, 555}} {196, 240} {{202, 428}, {480, 270}} @@ -258,6 +258,13 @@ YES + + NSApplication + + IBProjectSource + Frameworks/PSMTabBar/PSMTabDragAssistant.h + + NSObject @@ -272,6 +279,20 @@ Frameworks/MCPKit/MCPFoundationKit/MCPNull.h + + NSObject + + IBProjectSource + Frameworks/PSMTabBar/PSMTabBarCell.h + + + + NSObject + + IBProjectSource + Frameworks/PSMTabBar/PSMTabBarControl.h + + NSObject @@ -332,6 +353,50 @@ Source/SPWindowAdditions.h + + PSMTabBarControl + + IBProjectSource + Frameworks/PSMTabBar/PSMProgressIndicator.h + + + + PSMTabBarControl + + + + PSMTabBarControl + NSControl + + YES + + YES + delegate + partnerView + style + tabView + + + YES + id + id + id + NSTabView + + + + + + PSMTabBarControl + + + + PSMTabBarControl + + IBProjectSource + Frameworks/PSMTabBar/PSMTabStyle.h + + SPWindowController NSWindowController @@ -341,6 +406,8 @@ YES addNewConnection: closeTab: + selectNextDocumentTab: + selectPreviousDocumentTab: updateAllTabTitles: @@ -348,6 +415,8 @@ id id id + id + id @@ -710,6 +779,13 @@ PSMTabBar.framework/Headers/PSMTabBarControl.h + + NSObject + + IBFrameworkSource + Print.framework/Headers/PDEPluginInterface.h + + NSObject diff --git a/Source/SPDatabaseDocument.m b/Source/SPDatabaseDocument.m index e0ba899e..e06065af 100644 --- a/Source/SPDatabaseDocument.m +++ b/Source/SPDatabaseDocument.m @@ -3574,6 +3574,7 @@ // set up toolbar properties [mainToolbar setAllowsUserCustomization:YES]; [mainToolbar setAutosavesConfiguration:YES]; + [mainToolbar setShowsBaselineSeparator:NO]; [mainToolbar setDisplayMode:NSToolbarDisplayModeIconAndLabel]; // set ourself as the delegate diff --git a/Source/SPWindowController.m b/Source/SPWindowController.m index 91fc3cd5..eaa98997 100644 --- a/Source/SPWindowController.m +++ b/Source/SPWindowController.m @@ -51,7 +51,7 @@ managedDatabaseConnections = [[NSMutableArray alloc] init]; // Set up the tab bar - [tabBar setStyleNamed:@"Metal"]; + [tabBar setStyleNamed:@"SequelPro"]; [tabBar setCanCloseOnlyTab:NO]; [tabBar setHideForSingleTab:YES]; [tabBar setShowAddTabButton:YES]; diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj index f9ba43d5..4bb87056 100644 --- a/sequel-pro.xcodeproj/project.pbxproj +++ b/sequel-pro.xcodeproj/project.pbxproj @@ -267,6 +267,11 @@ B54F25E60FD909C400E2CF36 /* toolbar-switch-to-table-relations.png in Resources */ = {isa = PBXBuildFile; fileRef = B54F25E50FD909C400E2CF36 /* toolbar-switch-to-table-relations.png */; }; B5538AAF0FF251EE00219803 /* button_pane_hide_icon.tif in Resources */ = {isa = PBXBuildFile; fileRef = B5538AAC0FF251EE00219803 /* button_pane_hide_icon.tif */; }; B5538AB00FF251EE00219803 /* button_pane_show_icon.tif in Resources */ = {isa = PBXBuildFile; fileRef = B5538AAD0FF251EE00219803 /* button_pane_show_icon.tif */; }; + B55F8E5F11C67CA0006A3386 /* PSMSequelProTabStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */; }; + B55F8E6211C67D53006A3386 /* PSMSequelProTabStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */; }; + B55F8E6611C67D8A006A3386 /* AddTabButton.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6311C67D8A006A3386 /* AddTabButton.png */; }; + B55F8E6711C67D8A006A3386 /* AddTabButtonPushed.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */; }; + B55F8E6811C67D8A006A3386 /* AddTabButtonRollover.png in Resources */ = {isa = PBXBuildFile; fileRef = B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */; }; B57747D20F7A891A003B34F9 /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = B57747D00F7A891A003B34F9 /* Preferences.xib */; }; B57747D40F7A8974003B34F9 /* SPPreferenceController.m in Sources */ = {isa = PBXBuildFile; fileRef = B57747D30F7A8974003B34F9 /* SPPreferenceController.m */; }; B57747D90F7A8990003B34F9 /* SPWindowAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = B57747D80F7A8990003B34F9 /* SPWindowAdditions.m */; }; @@ -826,6 +831,11 @@ B54F25E50FD909C400E2CF36 /* toolbar-switch-to-table-relations.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "toolbar-switch-to-table-relations.png"; sourceTree = ""; }; B5538AAC0FF251EE00219803 /* button_pane_hide_icon.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = button_pane_hide_icon.tif; sourceTree = ""; }; B5538AAD0FF251EE00219803 /* button_pane_show_icon.tif */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = button_pane_show_icon.tif; sourceTree = ""; }; + B55F8E5D11C67CA0006A3386 /* PSMSequelProTabStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSMSequelProTabStyle.h; sourceTree = ""; }; + B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSMSequelProTabStyle.m; sourceTree = ""; }; + B55F8E6311C67D8A006A3386 /* AddTabButton.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButton.png; sourceTree = ""; }; + B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButtonPushed.png; sourceTree = ""; }; + B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = AddTabButtonRollover.png; sourceTree = ""; }; B57747D10F7A891A003B34F9 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/Preferences.xib; sourceTree = ""; }; B57747D30F7A8974003B34F9 /* SPPreferenceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SPPreferenceController.m; sourceTree = ""; }; B57747D50F7A8978003B34F9 /* SPPreferenceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SPPreferenceController.h; sourceTree = ""; }; @@ -1849,6 +1859,9 @@ isa = PBXGroup; children = ( 58B906FA11BD9B34000826E5 /* AdiumGradient.png */, + B55F8E6311C67D8A006A3386 /* AddTabButton.png */, + B55F8E6411C67D8A006A3386 /* AddTabButtonPushed.png */, + B55F8E6511C67D8A006A3386 /* AddTabButtonRollover.png */, 58B906FB11BD9B34000826E5 /* AquaTabClose_Front.png */, 58B906FC11BD9B34000826E5 /* AquaTabClose_Front_Pressed.png */, 58B906FD11BD9B34000826E5 /* AquaTabClose_Front_Rollover.png */, @@ -1891,6 +1904,8 @@ 58B9073511BD9B34000826E5 /* PSMCardTabStyle.m */, 58B9073611BD9B34000826E5 /* PSMMetalTabStyle.h */, 58B9073711BD9B34000826E5 /* PSMMetalTabStyle.m */, + B55F8E5D11C67CA0006A3386 /* PSMSequelProTabStyle.h */, + B55F8E5E11C67CA0006A3386 /* PSMSequelProTabStyle.m */, 58B9073811BD9B34000826E5 /* PSMUnifiedTabStyle.h */, 58B9073911BD9B34000826E5 /* PSMUnifiedTabStyle.m */, ); @@ -2159,6 +2174,9 @@ 58B9075311BD9B34000826E5 /* TabNewMetal.png in Resources */, 58B9075411BD9B34000826E5 /* TabNewMetalPressed.png in Resources */, 58B9075511BD9B34000826E5 /* TabNewMetalRollover.png in Resources */, + B55F8E6611C67D8A006A3386 /* AddTabButton.png in Resources */, + B55F8E6711C67D8A006A3386 /* AddTabButtonPushed.png in Resources */, + B55F8E6811C67D8A006A3386 /* AddTabButtonRollover.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2373,6 +2391,7 @@ 58B9076B11BD9B34000826E5 /* PSMTabDragWindow.m in Sources */, 58B9076D11BD9B34000826E5 /* PSMTabDragWindowController.m in Sources */, 58B9077611BD9B34000826E5 /* PSMMetalTabStyle.m in Sources */, + B55F8E6211C67D53006A3386 /* PSMSequelProTabStyle.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2502,6 +2521,7 @@ 173C839511AAD32A00B8B084 /* SPXMLExporterDelegate.m in Sources */, 58B909A511C3B919000826E5 /* DMLocalizedNibBundle.m in Sources */, 17A7773411C52D8E001E27B4 /* SPIndexesController.m in Sources */, + B55F8E5F11C67CA0006A3386 /* PSMSequelProTabStyle.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; -- cgit v1.2.3