aboutsummaryrefslogtreecommitdiffstats
path: root/Frameworks/PSMTabBar/Styles
diff options
context:
space:
mode:
Diffstat (limited to 'Frameworks/PSMTabBar/Styles')
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.h39
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.m1057
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.h38
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.m579
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMCardTabStyle.h32
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMCardTabStyle.m649
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.h34
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.m656
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.h30
-rw-r--r--Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.m603
10 files changed, 3717 insertions, 0 deletions
diff --git a/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.h
new file mode 100644
index 00000000..fac9a427
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.h
@@ -0,0 +1,39 @@
+//
+// PSMAdiumTabStyle.h
+// PSMTabBarControl
+//
+// Created by Kent Sutherland on 5/26/06.
+// Copyright 2006 Kent Sutherland. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSMTabStyle.h"
+
+@interface PSMAdiumTabStyle : NSObject <PSMTabStyle>
+{
+ NSImage *_closeButton, *_closeButtonDown, *_closeButtonOver;
+ NSImage *_closeDirtyButton, *_closeDirtyButtonDown, *_closeDirtyButtonOver;
+ NSImage *_addTabButtonImage, *_addTabButtonPressedImage, *_addTabButtonRolloverImage;
+ NSImage *_gradientImage;
+
+ NSDictionary *_objectCountStringAttributes;
+
+ PSMTabBarOrientation orientation;
+ PSMTabBarControl *tabBar;
+
+ BOOL _drawsUnified, _drawsRight;
+}
+
+- (void)loadImages;
+
+- (BOOL)drawsUnified;
+- (void)setDrawsUnified:(BOOL)value;
+- (BOOL)drawsRight;
+- (void)setDrawsRight:(BOOL)value;
+
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
+
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+- (id)initWithCoder:(NSCoder *)aDecoder;
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.m
new file mode 100644
index 00000000..be5cf82d
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMAdiumTabStyle.m
@@ -0,0 +1,1057 @@
+//
+// PSMAdiumTabStyle.m
+// PSMTabBarControl
+//
+// Created by Kent Sutherland on 5/26/06.
+// Copyright 2006 Kent Sutherland. All rights reserved.
+//
+
+#import "PSMAdiumTabStyle.h"
+#import "PSMTabBarCell.h"
+#import "PSMTabBarControl.h"
+#import "NSBezierPath_AMShading.h"
+
+#define Adium_CellPadding 2
+#define Adium_MARGIN_X 4
+#define kPSMAdiumCounterPadding 3.0
+#define kPSMAdiumObjectCounterRadius 7.0
+#define kPSMAdiumCounterMinWidth 20
+
+#define kPSMTabBarControlSourceListHeight 28
+
+#define kPSMTabBarLargeImageHeight kPSMTabBarControlSourceListHeight - 4
+#define kPSMTabBarLargeImageWidth kPSMTabBarLargeImageHeight
+
+@implementation PSMAdiumTabStyle
+
+- (NSString *)name
+{
+ return @"Adium";
+}
+
+#pragma mark -
+#pragma mark Creation/Destruction
+
+- (id)init
+{
+ if ( (self = [super init]) ) {
+ [self loadImages];
+ _drawsUnified = NO;
+ _drawsRight = NO;
+
+ _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)loadImages
+{
+ _closeButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front"]];
+ _closeButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Pressed"]];
+ _closeButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Rollover"]];
+
+ _closeDirtyButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front"]];
+ _closeDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Pressed"]];
+ _closeDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Rollover"]];
+
+ _addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNew"]];
+ _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewPressed"]];
+ _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewRollover"]];
+
+ _gradientImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AdiumGradient"]];
+}
+
+- (void)dealloc
+{
+ [_closeButton release];
+ [_closeButtonDown release];
+ [_closeButtonOver release];
+
+ [_closeDirtyButton release];
+ [_closeDirtyButtonDown release];
+ [_closeDirtyButtonOver release];
+
+ [_addTabButtonImage release];
+ [_addTabButtonPressedImage release];
+ [_addTabButtonRolloverImage release];
+
+ [_gradientImage release];
+
+ [_objectCountStringAttributes release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Drawing Style Accessors
+
+- (BOOL)drawsUnified
+{
+ return _drawsUnified;
+}
+
+- (void)setDrawsUnified:(BOOL)value
+{
+ _drawsUnified = value;
+}
+
+- (BOOL)drawsRight
+{
+ return _drawsRight;
+}
+
+- (void)setDrawsRight:(BOOL)value
+{
+ _drawsRight = value;
+}
+
+#pragma mark -
+#pragma mark Control Specific
+
+- (CGFloat)leftMarginForTabBarControl
+{
+ return 3.0f;
+}
+
+- (CGFloat)rightMarginForTabBarControl
+{
+ return 24.0f;
+}
+
+- (CGFloat)topMarginForTabBarControl
+{
+ return 10.0f;
+}
+
+- (void)setOrientation:(PSMTabBarOrientation)value
+{
+ orientation = value;
+}
+
+#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];
+
+ if ([cell tabState] & PSMTab_SelectedMask) {
+ if (tabOrientation == PSMTabBarHorizontalOrientation) {
+ dragRect.size.width++;
+ dragRect.size.height -= 2.0;
+ }
+ }
+
+ return dragRect;
+}
+
+- (BOOL)closeButtonIsEnabledForCell:(PSMTabBarCell *)cell
+{
+ return ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]);
+
+}
+- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame
+{
+ if ([self closeButtonIsEnabledForCell:cell] == NO) {
+ return NSZeroRect;
+ }
+
+ NSRect result;
+ result.size = [_closeButton size];
+
+ switch (orientation) {
+ case PSMTabBarHorizontalOrientation:
+ {
+ result.origin.x = cellFrame.origin.x + Adium_MARGIN_X;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y + 2.0;
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+ break;
+ }
+
+ case PSMTabBarVerticalOrientation:
+ {
+ result.origin.x = NSMaxX(cellFrame) - (Adium_MARGIN_X*2) - NSWidth(result);
+ result.origin.y = NSMinY(cellFrame) + (NSHeight(cellFrame) / 2) - (result.size.height / 2) + 1;
+ break;
+ }
+ }
+
+ return result;
+}
+
+- (NSRect)iconRectForTabCell:(PSMTabBarCell *)cell
+{
+ if ([cell hasIcon] == NO) {
+ return NSZeroRect;
+ }
+
+ NSRect cellFrame = [cell frame];
+ NSImage *icon = [[[cell representedObject] identifier] icon];
+ NSSize iconSize = [icon size];
+
+ NSRect result;
+ result.size = iconSize;
+
+ switch (orientation)
+ {
+ case PSMTabBarHorizontalOrientation:
+ result.origin.x = cellFrame.origin.x + Adium_MARGIN_X;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y;
+ break;
+
+ case PSMTabBarVerticalOrientation:
+ result.origin.x = NSMaxX(cellFrame) - (Adium_MARGIN_X * 2) - NSWidth(result);
+ result.origin.y = NSMinY(cellFrame) + (NSHeight(cellFrame) / 2) - (NSHeight(result) / 2) + 1;
+ break;
+ }
+
+ // For horizontal tabs, center in available space (in case icon image is smaller than kPSMTabBarIconWidth)
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ if (iconSize.width < kPSMTabBarIconWidth)
+ result.origin.x += (kPSMTabBarIconWidth - iconSize.width) / 2.0;
+ if (iconSize.height < kPSMTabBarIconWidth)
+ result.origin.y += (kPSMTabBarIconWidth - iconSize.height) / 2.0;
+ }
+
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+
+ 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 - Adium_MARGIN_X - kPSMTabBarIndicatorWidth;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y;
+
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+
+ return result;
+}
+
+- (NSSize)sizeForObjectCounterRectForTabCell:(PSMTabBarCell *)cell
+{
+ NSSize size;
+ CGFloat countWidth = [[self attributedObjectCountValueForTabCell:cell] size].width;
+
+ countWidth += (2 * kPSMAdiumObjectCounterRadius - 6.0 + kPSMAdiumCounterPadding);
+
+ if (countWidth < kPSMAdiumCounterMinWidth) {
+ countWidth = kPSMAdiumCounterMinWidth;
+ }
+
+ size = NSMakeSize(countWidth, 2 * kPSMAdiumObjectCounterRadius); // temp
+
+ return size;
+}
+
+- (NSRect)objectCounterRectForTabCell:(PSMTabBarCell *)cell
+{
+ NSRect cellFrame;
+ NSRect result;
+
+ if ([cell count] == 0) {
+ return NSZeroRect;
+ }
+
+ cellFrame = [cell frame];
+ result.size = [self sizeForObjectCounterRectForTabCell:cell];
+ result.origin.x = NSMaxX(cellFrame) - Adium_MARGIN_X - result.size.width;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0;
+
+ if (![[cell indicator] isHidden]) {
+ result.origin.x -= kPSMTabBarIndicatorWidth + Adium_CellPadding;
+ }
+
+ return result;
+}
+
+- (CGFloat)minimumWidthOfTabCell:(PSMTabBarCell *)cell
+{
+ CGFloat resultWidth = 0.0;
+
+ // left margin
+ resultWidth = Adium_MARGIN_X;
+
+ // close button?
+ if ([self closeButtonIsEnabledForCell:cell]) {
+ resultWidth += MAX([_closeButton size].width, NSWidth([self iconRectForTabCell:cell])) + Adium_CellPadding;
+ }
+
+ // icon?
+ /*if ([cell hasIcon]) {
+ resultWidth += kPSMTabBarIconWidth + Adium_CellPadding;
+ }*/
+
+ // the label
+ resultWidth += kPSMMinimumTitleWidth;
+
+ // object counter?
+ if (([cell count] > 0) && (orientation == PSMTabBarHorizontalOrientation)) {
+ resultWidth += NSWidth([self objectCounterRectForTabCell:cell]) + Adium_CellPadding;
+ }
+
+ // indicator?
+ if ([[cell indicator] isHidden] == NO) {
+ resultWidth += Adium_CellPadding + kPSMTabBarIndicatorWidth;
+ }
+
+ // right margin
+ resultWidth += Adium_MARGIN_X;
+
+ return ceil(resultWidth);
+}
+
+- (CGFloat)desiredWidthOfTabCell:(PSMTabBarCell *)cell
+{
+ CGFloat resultWidth = 0.0;
+
+ // left margin
+ resultWidth = Adium_MARGIN_X;
+
+ // close button?
+ if ([self closeButtonIsEnabledForCell:cell]) {
+ resultWidth += MAX([_closeButton size].width, NSWidth([self iconRectForTabCell:cell])) + Adium_CellPadding;
+ }
+
+ // icon?
+ /*if ([cell hasIcon]) {
+ resultWidth += kPSMTabBarIconWidth + Adium_CellPadding;
+ }*/
+
+ // the label
+ resultWidth += [[cell attributedStringValue] size].width + Adium_CellPadding;
+
+ // object counter?
+ if (([cell count] > 0) && (orientation == PSMTabBarHorizontalOrientation)){
+ resultWidth += [self objectCounterRectForTabCell:cell].size.width + Adium_CellPadding;
+ }
+
+ // indicator?
+ if ([[cell indicator] isHidden] == NO) {
+ resultWidth += Adium_CellPadding + kPSMTabBarIndicatorWidth;
+ }
+
+ // right margin
+ resultWidth += Adium_MARGIN_X;
+
+ return ceil(resultWidth);
+}
+
+- (CGFloat)tabCellHeight
+{
+ return ((orientation == PSMTabBarHorizontalOrientation) ? kPSMTabBarControlHeight : kPSMTabBarControlSourceListHeight);
+}
+
+#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 systemFontOfSize:11.0] range:range];
+ [attrStr addAttribute:NSForegroundColorAttributeName value:[NSColor controlTextColor] range:range];
+
+ // Paragraph Style for Truncating Long Text
+ static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil;
+ if (!TruncatingTailParagraphStyle) {
+ TruncatingTailParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain];
+ [TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
+ }
+ [attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range];
+
+ return attrStr;
+}
+
+#pragma mark -
+#pragma mark Cell Drawing
+
+- (CGFloat)heightOfAttributedString:(NSAttributedString *)inAttributedString withWidth:(CGFloat)width
+{
+ static NSMutableDictionary *cache;
+ if (!cache)
+ cache = [[NSMutableDictionary alloc] init];
+ if ([cache count] > 100) //100 items should be trivial in terms of memory overhead, but sufficient
+ [cache removeAllObjects];
+ NSNumber *cachedHeight = [cache objectForKey:inAttributedString];
+ if (cachedHeight)
+ return [cachedHeight doubleValue];
+ else {
+ NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:inAttributedString];
+ NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:NSMakeSize(width, 1e7)];
+ NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
+
+ //Configure
+ [textContainer setLineFragmentPadding:0.0];
+ [layoutManager addTextContainer:textContainer];
+ [textStorage addLayoutManager:layoutManager];
+
+ //Force the layout manager to layout its text
+ (void)[layoutManager glyphRangeForTextContainer:textContainer];
+
+ CGFloat height = [layoutManager usedRectForTextContainer:textContainer].size.height;
+
+ [textStorage release];
+ [textContainer release];
+ [layoutManager release];
+
+ [cache setObject:[NSNumber numberWithDouble:height] forKey:inAttributedString];
+
+ return height;
+ }
+}
+
+- (void)drawObjectCounterInCell:(PSMTabBarCell *)cell withRect:(NSRect)myRect
+{
+ myRect.size.width -= kPSMAdiumCounterPadding;
+ myRect.origin.x += kPSMAdiumCounterPadding;
+
+ [[cell countColor] ?: [NSColor colorWithCalibratedWhite:0.3 alpha:0.6] set];
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ [path setLineWidth:1.0];
+
+ if ([cell state] == NSOnState) {
+ myRect.origin.y -= 1.0;
+ }
+
+ [path moveToPoint:NSMakePoint(NSMinX(myRect) + kPSMAdiumObjectCounterRadius, NSMinY(myRect))];
+ [path lineToPoint:NSMakePoint(NSMaxX(myRect) - kPSMAdiumObjectCounterRadius, NSMinY(myRect))];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(myRect) - kPSMAdiumObjectCounterRadius, NSMinY(myRect) + kPSMAdiumObjectCounterRadius)
+ radius:kPSMAdiumObjectCounterRadius
+ startAngle:270.0
+ endAngle:90.0];
+ [path lineToPoint:NSMakePoint(NSMinX(myRect) + kPSMAdiumObjectCounterRadius, NSMaxY(myRect))];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(myRect) + kPSMAdiumObjectCounterRadius, NSMinY(myRect) + kPSMAdiumObjectCounterRadius)
+ radius:kPSMAdiumObjectCounterRadius
+ 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];
+}
+
+- (NSBezierPath *)bezierPathWithRoundedRect:(NSRect)rect radius:(CGFloat)radius
+{
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ NSPoint topLeft, topRight, bottomLeft, bottomRight;
+
+ topLeft = NSMakePoint(rect.origin.x, rect.origin.y);
+ topRight = NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y);
+ bottomLeft = NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height);
+ bottomRight = NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(topLeft.x + radius, topLeft.y + radius)
+ radius:radius
+ startAngle:180
+ endAngle:270
+ clockwise:NO];
+ [path lineToPoint:NSMakePoint(topRight.x - radius, topRight.y)];
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(topRight.x - radius, topRight.y + radius)
+ radius:radius
+ startAngle:270
+ endAngle:0
+ clockwise:NO];
+ [path lineToPoint:NSMakePoint(bottomRight.x, bottomRight.y - radius)];
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(bottomRight.x - radius, bottomRight.y - radius)
+ radius:radius
+ startAngle:0
+ endAngle:90
+ clockwise:NO];
+ [path lineToPoint:NSMakePoint(bottomLeft.x + radius, bottomLeft.y)];
+
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(bottomLeft.x + radius, bottomLeft.y - radius)
+ radius:radius
+ startAngle:90
+ endAngle:180
+ clockwise:NO];
+ [path lineToPoint:NSMakePoint(topLeft.x, topLeft.y + radius)];
+
+ return path;
+}
+
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView
+{
+ NSRect cellFrame = [cell frame];
+
+ if ((orientation == PSMTabBarVerticalOrientation) &&
+ [cell hasLargeImage]) {
+ NSImage *image = [[[cell representedObject] identifier] largeImage];
+ cellFrame.origin.x += Adium_MARGIN_X;
+
+ NSRect imageDrawingRect = NSMakeRect(cellFrame.origin.x,
+ cellFrame.origin.y - ((kPSMTabBarControlSourceListHeight - kPSMTabBarLargeImageHeight) / 2),
+ kPSMTabBarLargeImageWidth, kPSMTabBarLargeImageHeight);
+
+ [NSGraphicsContext saveGraphicsState];
+ //Use a transform to draw an arbitrary image in our flipped view
+ NSAffineTransform *transform = [NSAffineTransform transform];
+ [transform translateXBy:imageDrawingRect.origin.x yBy:(imageDrawingRect.origin.y + imageDrawingRect.size.height)];
+ [transform scaleXBy:1.0 yBy:-1.0];
+ [transform concat];
+
+ imageDrawingRect.origin = NSMakePoint(0,0);
+
+ //Create Rounding.
+ CGFloat userIconRoundingRadius = (kPSMTabBarLargeImageWidth / 4.0);
+ if (userIconRoundingRadius > 3) userIconRoundingRadius = 3;
+ NSBezierPath *clipPath = [self bezierPathWithRoundedRect:imageDrawingRect radius:userIconRoundingRadius];
+ [clipPath addClip];
+
+ [image drawInRect:imageDrawingRect
+ fromRect:NSMakeRect(0, 0, [image size].width, [image size].height)
+ operation:NSCompositeSourceOver
+ fraction:1.0];
+
+ [NSGraphicsContext restoreGraphicsState];
+
+ cellFrame.origin.x += imageDrawingRect.size.width;
+ cellFrame.size.width -= imageDrawingRect.size.width;
+ }
+
+ // label rect
+ NSRect labelRect;
+ labelRect.origin.x = cellFrame.origin.x + Adium_MARGIN_X;
+ labelRect.size.width = cellFrame.size.width - (labelRect.origin.x - cellFrame.origin.x) - Adium_CellPadding;
+ labelRect.size.height = cellFrame.size.height;
+ switch (orientation)
+ {
+ case PSMTabBarHorizontalOrientation:
+ labelRect.origin.y = cellFrame.origin.y + MARGIN_Y + 1.0;
+ break;
+ case PSMTabBarVerticalOrientation:
+ labelRect.origin.y = cellFrame.origin.y;
+ break;
+ }
+
+ if ([self closeButtonIsEnabledForCell:cell]) {
+ /* The close button and the icon (if present) are drawn combined, changing on-hover */
+ NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
+ NSRect iconRect = [self iconRectForTabCell:cell];
+ NSRect drawingRect;
+ NSImage *closeButtonOrIcon = nil;
+
+ if ([cell hasIcon]) {
+ /* If the cell has an icon and a close button, determine which rect should be used and use it consistently
+ * This only matters for horizontal tabs; vertical tabs look fine without making this adjustment.
+ */
+ if (NSWidth(iconRect) > NSWidth(closeButtonRect)) {
+ closeButtonRect.origin.x = NSMinX(iconRect) + NSWidth(iconRect)/2 - NSWidth(closeButtonRect)/2;
+ }
+ }
+
+ if ([cell closeButtonPressed]) {
+ closeButtonOrIcon = ([cell isEdited] ? _closeDirtyButtonDown : _closeButtonDown);
+ drawingRect = closeButtonRect;
+
+ } else if ([cell closeButtonOver]) {
+ closeButtonOrIcon = ([cell isEdited] ? _closeDirtyButtonOver : _closeButtonOver);
+ drawingRect = closeButtonRect;
+
+ } else if ((orientation == PSMTabBarVerticalOrientation) &&
+ ([cell count] > 0)) {
+ /* In vertical tabs, the count indicator supercedes the icon */
+ NSSize counterSize = [self sizeForObjectCounterRectForTabCell:cell];
+ if (counterSize.width > NSWidth(closeButtonRect)) {
+ closeButtonRect.origin.x -= (counterSize.width - NSWidth(closeButtonRect));
+ closeButtonRect.size.width = counterSize.width;
+ }
+
+ closeButtonRect.origin.y = cellFrame.origin.y + ((NSHeight(cellFrame) - counterSize.height) / 2);
+ closeButtonRect.size.height = counterSize.height;
+
+ drawingRect = closeButtonRect;
+ [self drawObjectCounterInCell:cell withRect:drawingRect];
+ /* closeButtonOrIcon == nil */
+
+ } else if ([cell hasIcon]) {
+ closeButtonOrIcon = [[[cell representedObject] identifier] icon];
+ drawingRect = iconRect;
+
+ } else {
+ closeButtonOrIcon = ([cell isEdited] ? _closeDirtyButton : _closeButton);
+ drawingRect = closeButtonRect;
+ }
+
+ if ([controlView isFlipped]) {
+ drawingRect.origin.y += drawingRect.size.height;
+ }
+
+ [closeButtonOrIcon compositeToPoint:drawingRect.origin operation:NSCompositeSourceOver fraction:1.0];
+
+ // scoot label over
+ switch (orientation)
+ {
+ case PSMTabBarHorizontalOrientation:
+ {
+ CGFloat oldOrigin = labelRect.origin.x;
+ if (NSWidth(iconRect) > NSWidth(closeButtonRect)) {
+ labelRect.origin.x = (NSMaxX(iconRect) + (Adium_CellPadding * 2));
+ } else {
+ labelRect.origin.x = (NSMaxX(closeButtonRect) + (Adium_CellPadding * 2));
+ }
+ labelRect.size.width -= (NSMinX(labelRect) - oldOrigin);
+ break;
+ }
+ case PSMTabBarVerticalOrientation:
+ {
+ //Generate the remaining label rect directly from the location of the close button, allowing for padding
+ if (NSWidth(iconRect) > NSWidth(closeButtonRect)) {
+ labelRect.size.width = NSMinX(iconRect) - Adium_CellPadding - NSMinX(labelRect);
+ } else {
+ labelRect.size.width = NSMinX(closeButtonRect) - Adium_CellPadding - NSMinX(labelRect);
+ }
+
+ break;
+ }
+ }
+
+ } else if ([cell hasIcon]) {
+ /* The close button is disabled; the cell has an icon */
+ NSRect iconRect = [self iconRectForTabCell:cell];
+ NSImage *icon = [[[cell representedObject] identifier] icon];
+
+ if ([controlView isFlipped]) {
+ iconRect.origin.y += iconRect.size.height;
+ }
+
+ [icon compositeToPoint:iconRect.origin operation:NSCompositeSourceOver fraction:1.0];
+
+ // scoot label over by the size of the standard close button
+ switch (orientation)
+ {
+ case PSMTabBarHorizontalOrientation:
+ labelRect.origin.x += (NSWidth(iconRect) + Adium_CellPadding);
+ labelRect.size.width -= (NSWidth(iconRect) + Adium_CellPadding);
+ break;
+ case PSMTabBarVerticalOrientation:
+ labelRect.size.width -= (NSWidth(iconRect) + Adium_CellPadding);
+ break;
+ }
+ }
+
+ if ([cell state] == NSOnState) {
+ labelRect.origin.y -= 1;
+ }
+
+ if (![[cell indicator] isHidden]) {
+ labelRect.size.width -= (kPSMTabBarIndicatorWidth + Adium_CellPadding);
+ }
+
+ // object counter
+ //The object counter takes up space horizontally...
+ if (([cell count] > 0) &&
+ (orientation == PSMTabBarHorizontalOrientation)) {
+ NSRect counterRect = [self objectCounterRectForTabCell:cell];
+
+ [self drawObjectCounterInCell:cell withRect:counterRect];
+ labelRect.size.width -= NSWidth(counterRect) + Adium_CellPadding;
+ }
+
+ // draw label
+ NSAttributedString *attributedString = [cell attributedStringValue];
+ if (orientation == PSMTabBarVerticalOrientation) {
+ //Calculate the centered rect
+ CGFloat stringHeight = [self heightOfAttributedString:attributedString withWidth:NSWidth(labelRect)];
+ if (stringHeight < labelRect.size.height) {
+ labelRect.origin.y += (NSHeight(labelRect) - stringHeight) / 2.0;
+ }
+ }
+
+ [attributedString drawInRect:labelRect];
+}
+
+- (void)drawTabCell:(PSMTabBarCell *)cell
+{
+ NSRect cellFrame = [cell frame];
+ NSColor *lineColor = nil;
+ NSBezierPath *bezier = [NSBezierPath bezierPath];
+ lineColor = [NSColor grayColor];
+
+ [bezier setLineWidth:1.0];
+
+ //disable antialiasing of bezier paths
+ [NSGraphicsContext saveGraphicsState];
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ NSShadow *shadow = [[NSShadow alloc] init];
+ [shadow setShadowOffset:NSMakeSize(-2, -2)];
+ [shadow setShadowBlurRadius:2];
+ [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.6 alpha:1.0]];
+
+ if ([cell state] == NSOnState) {
+ // selected tab
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, NSWidth(cellFrame), cellFrame.size.height - 2.5);
+
+ // background
+ if (_drawsUnified) {
+ if ([[[tabBar tabView] window] isKeyWindow]) {
+ NSBezierPath *path = [NSBezierPath bezierPathWithRect:aRect];
+ [path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ } else {
+ [[NSColor windowBackgroundColor] set];
+ NSRectFill(aRect);
+ }
+ } else {
+ [_gradientImage drawInRect:NSMakeRect(NSMinX(aRect), NSMinY(aRect), NSWidth(aRect), NSHeight(aRect)) fromRect:NSMakeRect(0, 0, [_gradientImage size].width, [_gradientImage size].height) operation:NSCompositeSourceOver fraction:1.0];
+ }
+
+ // frame
+ [lineColor set];
+ [bezier setLineWidth:1.0];
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y + aRect.size.height)];
+
+ [shadow setShadowOffset:NSMakeSize(-2, -2)];
+ [shadow set];
+ [bezier stroke];
+
+ bezier = [NSBezierPath bezierPath];
+ [bezier setLineWidth:1.0];
+ [bezier moveToPoint:NSMakePoint(NSMinX(aRect), NSMaxY(aRect))];
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];
+
+ if ([[cell controlView] frame].size.height < 2) {
+ // special case of hidden control; need line across top of cell
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y + 0.5)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+aRect.size.width, aRect.origin.y + 0.5)];
+ }
+
+ [shadow setShadowOffset:NSMakeSize(2, -2)];
+ [shadow set];
+ [bezier stroke];
+ } else {
+ NSRect aRect;
+
+ if (_drawsRight) {
+ aRect = NSMakeRect(cellFrame.origin.x - 1, cellFrame.origin.y, cellFrame.size.width - 3, cellFrame.size.height);
+ } else {
+ aRect = NSMakeRect(cellFrame.origin.x + 2, cellFrame.origin.y, cellFrame.size.width - 2, cellFrame.size.height);
+ }
+
+ // background
+ if (_drawsUnified) {
+ if ([[[tabBar tabView] window] isKeyWindow]) {
+ NSBezierPath *path = [NSBezierPath bezierPathWithRect:aRect];
+ [path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ } else {
+ [[NSColor windowBackgroundColor] set];
+ NSRectFill(aRect);
+ }
+ } else {
+ NSBezierPath *path = [NSBezierPath bezierPathWithRect:aRect];
+ if (_drawsRight) {
+ [path linearVerticalGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.92 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.98 alpha:1.0]];
+ } else {
+ [path linearVerticalGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.98 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.92 alpha:1.0]];
+ }
+ }
+
+ // frame
+ //top line
+ [lineColor set];
+ [bezier setLineWidth:1.0];
+ [bezier moveToPoint:NSMakePoint(NSMinX(aRect), NSMinY(aRect))];
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];
+ [bezier stroke];
+
+ //outer edge and bottom lines
+ bezier = [NSBezierPath bezierPath];
+ [bezier setLineWidth:1.0];
+ if (_drawsRight) {
+ //Right
+ [bezier moveToPoint:NSMakePoint(NSMaxX(aRect), NSMinY(aRect))];
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
+ //Bottom
+ [bezier lineToPoint:NSMakePoint(NSMinX(aRect), NSMaxY(aRect))];
+ } else {
+ //Left
+ [bezier moveToPoint:NSMakePoint(NSMinX(aRect), NSMinY(aRect))];
+ [bezier lineToPoint:NSMakePoint(NSMinX(aRect), NSMaxY(aRect))];
+ //Bottom
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
+ }
+ [shadow setShadowOffset:NSMakeSize((_drawsRight ? 2 : -2), -2)];
+ [shadow set];
+ [bezier stroke];
+ }
+ } else {
+ // unselected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
+
+ // rollover
+ if ([cell isHighlighted]) {
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
+ NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
+ }
+
+ // frame
+ [lineColor set];
+
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y)];
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ //draw the tab divider
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + aRect.size.height)];
+ }
+ [bezier stroke];
+
+ } else {
+ //No outline for vertical
+ }
+ }
+
+ [NSGraphicsContext restoreGraphicsState];
+ [shadow release];
+
+ [self drawInteriorWithTabCell:cell inView:[cell controlView]];
+}
+
+- (void)drawBackgroundInRect:(NSRect)rect
+{
+ //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area
+ rect = [tabBar bounds];
+
+ switch (orientation) {
+ case PSMTabBarHorizontalOrientation:
+ if (_drawsUnified && [[[tabBar tabView] window] isKeyWindow]) {
+ if ([[[tabBar tabView] window] isKeyWindow]) {
+ NSBezierPath *backgroundPath = [NSBezierPath bezierPathWithRect:rect];
+ [backgroundPath linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ } else {
+ [[NSColor windowBackgroundColor] set];
+ NSRectFill(rect);
+ }
+ } else {
+ [[NSColor colorWithCalibratedWhite:0.85 alpha:0.6] set];
+ [NSBezierPath fillRect:rect];
+ }
+ break;
+
+ case PSMTabBarVerticalOrientation:
+ //This is the Mail.app source list background color... which differs from the iTunes one.
+ [[NSColor colorWithCalibratedRed:.9059
+ green:.9294
+ blue:.9647
+ alpha:1.0] set];
+ NSRectFill(rect);
+ break;
+ }
+
+ //Draw the border and shadow around the tab bar itself
+ [NSGraphicsContext saveGraphicsState];
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ NSShadow *shadow = [[NSShadow alloc] init];
+ [shadow setShadowBlurRadius:2];
+ [shadow setShadowColor:[NSColor colorWithCalibratedWhite:0.6 alpha:1.0]];
+
+ [[NSColor grayColor] set];
+
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ [path setLineWidth:1.0];
+
+ switch (orientation) {
+ case PSMTabBarHorizontalOrientation:
+ {
+ rect.origin.y++;
+ [path moveToPoint:NSMakePoint(rect.origin.x, rect.origin.y)];
+ [path lineToPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y)];
+ [shadow setShadowOffset:NSMakeSize(2, -2)];
+
+ [shadow set];
+ [path stroke];
+
+ break;
+ }
+
+ case PSMTabBarVerticalOrientation:
+ {
+ NSPoint startPoint, endPoint;
+ NSSize shadowOffset;
+
+ //Draw vertical shadow
+ if (_drawsRight) {
+ startPoint = NSMakePoint(NSMinX(rect), NSMinY(rect));
+ endPoint = NSMakePoint(NSMinX(rect), NSMaxY(rect));
+ shadowOffset = NSMakeSize(2, -2);
+ } else {
+ startPoint = NSMakePoint(NSMaxX(rect) - 1, NSMinY(rect));
+ endPoint = NSMakePoint(NSMaxX(rect) - 1, NSMaxY(rect));
+ shadowOffset = NSMakeSize(-2, -2);
+ }
+
+ [path moveToPoint:startPoint];
+ [path lineToPoint:endPoint];
+ [shadow setShadowOffset:shadowOffset];
+
+ [shadow set];
+ [path stroke];
+
+ [path removeAllPoints];
+
+ //Draw top horizontal shadow
+ startPoint = NSMakePoint(NSMinX(rect), NSMinY(rect));
+ endPoint = NSMakePoint(NSMaxX(rect), NSMinY(rect));
+ shadowOffset = NSMakeSize(0, -1);
+
+ [path moveToPoint:startPoint];
+ [path lineToPoint:endPoint];
+ [shadow setShadowOffset:shadowOffset];
+
+ [shadow set];
+ [path stroke];
+
+ break;
+ }
+ }
+
+ [shadow release];
+ [NSGraphicsContext restoreGraphicsState];
+}
+
+- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
+{
+ if (orientation != [bar orientation]) {
+ orientation = [bar orientation];
+ }
+
+ if (tabBar != bar) {
+ [tabBar release];
+ tabBar = [bar retain];
+ }
+
+ [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;
+ while ( (cell = [e nextObject]) ) {
+ if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) {
+ [cell drawWithFrame:[cell frame] inView:bar];
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark Archiving
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+ if ([aCoder allowsKeyedCoding]) {
+ [aCoder encodeObject:_closeButton forKey:@"closeButton"];
+ [aCoder encodeObject:_closeButtonDown forKey:@"closeButtonDown"];
+ [aCoder encodeObject:_closeButtonOver forKey:@"closeButtonOver"];
+ [aCoder encodeObject:_closeDirtyButton forKey:@"closeDirtyButton"];
+ [aCoder encodeObject:_closeDirtyButtonDown forKey:@"closeDirtyButtonDown"];
+ [aCoder encodeObject:_closeDirtyButtonOver forKey:@"closeDirtyButtonOver"];
+ [aCoder encodeObject:_addTabButtonImage forKey:@"addTabButtonImage"];
+ [aCoder encodeObject:_addTabButtonPressedImage forKey:@"addTabButtonPressedImage"];
+ [aCoder encodeObject:_addTabButtonRolloverImage forKey:@"addTabButtonRolloverImage"];
+ [aCoder encodeBool:_drawsUnified forKey:@"drawsUnified"];
+ [aCoder encodeBool:_drawsRight forKey:@"drawsRight"];
+ }
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+ if ( (self = [super init]) ) {
+ if ([aDecoder allowsKeyedCoding]) {
+ _closeButton = [[aDecoder decodeObjectForKey:@"closeButton"] retain];
+ _closeButtonDown = [[aDecoder decodeObjectForKey:@"closeButtonDown"] retain];
+ _closeButtonOver = [[aDecoder decodeObjectForKey:@"closeButtonOver"] retain];
+ _closeDirtyButton = [[aDecoder decodeObjectForKey:@"closeDirtyButton"] retain];
+ _closeDirtyButtonDown = [[aDecoder decodeObjectForKey:@"closeDirtyButtonDown"] retain];
+ _closeDirtyButtonOver = [[aDecoder decodeObjectForKey:@"closeDirtyButtonOver"] retain];
+ _addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain];
+ _addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain];
+ _addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain];
+ _drawsUnified = [aDecoder decodeBoolForKey:@"drawsUnified"];
+ _drawsRight = [aDecoder decodeBoolForKey:@"drawsRight"];
+ }
+ }
+ return self;
+}
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.h
new file mode 100644
index 00000000..d3448e41
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.h
@@ -0,0 +1,38 @@
+//
+// PSMAquaTabStyle.h
+// PSMTabBarControl
+//
+// Created by John Pannell on 2/17/06.
+// Copyright 2006 Positive Spin Media. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSMTabStyle.h"
+
+@interface PSMAquaTabStyle : NSObject <PSMTabStyle> {
+ NSImage *aquaTabBg;
+ NSImage *aquaTabBgDown;
+ NSImage *aquaTabBgDownGraphite;
+ NSImage *aquaTabBgDownNonKey;
+ NSImage *aquaDividerDown;
+ NSImage *aquaDivider;
+ NSImage *aquaCloseButton;
+ NSImage *aquaCloseButtonDown;
+ NSImage *aquaCloseButtonOver;
+ NSImage *aquaCloseDirtyButton;
+ NSImage *aquaCloseDirtyButtonDown;
+ NSImage *aquaCloseDirtyButtonOver;
+ NSImage *_addTabButtonImage;
+ NSImage *_addTabButtonPressedImage;
+ NSImage *_addTabButtonRolloverImage;
+
+ NSDictionary *_objectCountStringAttributes;
+ PSMTabBarControl *tabBar;
+}
+
+- (void)loadImages;
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
+
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+- (id)initWithCoder:(NSCoder *)aDecoder;
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.m
new file mode 100644
index 00000000..f2618fe5
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMAquaTabStyle.m
@@ -0,0 +1,579 @@
+//
+// PSMAquaTabStyle.m
+// PSMTabBarControl
+//
+// Created by John Pannell on 2/17/06.
+// Copyright 2006 Positive Spin Media. All rights reserved.
+//
+
+#import "PSMAquaTabStyle.h"
+#import "PSMTabBarCell.h"
+#import "PSMTabBarControl.h"
+
+#define kPSMAquaObjectCounterRadius 7.0
+#define kPSMAquaCounterMinWidth 20
+
+@implementation PSMAquaTabStyle
+
+- (NSString *)name
+{
+ return @"Aqua";
+}
+
+#pragma mark -
+#pragma mark Creation/Destruction
+
+- (id) init
+{
+ if ( (self = [super init]) ) {
+ [self loadImages];
+
+ _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) loadImages
+{
+ // Aqua Tabs Images
+ aquaTabBg = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsBackground"]];
+ [aquaTabBg setFlipped:YES];
+
+ aquaTabBgDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsDown"]];
+ [aquaTabBgDown setFlipped:YES];
+
+ aquaTabBgDownGraphite = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsDownGraphite"]];
+ [aquaTabBgDown setFlipped:YES];
+
+ aquaTabBgDownNonKey = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsDownNonKey"]];
+ [aquaTabBgDown setFlipped:YES];
+
+ aquaDividerDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsSeparatorDown"]];
+ [aquaDivider setFlipped:NO];
+
+ aquaDivider = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabsSeparator"]];
+ [aquaDivider setFlipped:NO];
+
+ aquaCloseButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front"]];
+ aquaCloseButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Pressed"]];
+ aquaCloseButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Rollover"]];
+
+ aquaCloseDirtyButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front"]];
+ aquaCloseDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Pressed"]];
+ aquaCloseDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Rollover"]];
+
+ _addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNew"]];
+ _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewPressed"]];
+ _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewRollover"]];
+}
+
+- (void)dealloc
+{
+ [aquaTabBg release];
+ [aquaTabBgDown release];
+ [aquaDividerDown release];
+ [aquaDivider release];
+ [aquaCloseButton release];
+ [aquaCloseButtonDown release];
+ [aquaCloseButtonOver release];
+ [aquaCloseDirtyButton release];
+ [aquaCloseDirtyButtonDown release];
+ [aquaCloseDirtyButtonOver release];
+ [_addTabButtonImage release];
+ [_addTabButtonPressedImage release];
+ [_addTabButtonRolloverImage release];
+
+ [_objectCountStringAttributes release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Control Specifics
+
+- (CGFloat)leftMarginForTabBarControl
+{
+ return 0.0f;
+}
+
+- (CGFloat)rightMarginForTabBarControl
+{
+ return 24.0f;
+}
+
+- (CGFloat)topMarginForTabBarControl
+{
+ return 0.0f;
+}
+
+- (void)setOrientation:(PSMTabBarOrientation)value
+{
+
+}
+
+#pragma mark -
+#pragma mark Add Tab Button
+
+- (NSImage *)addTabButtonImage
+{
+ return _addTabButtonImage;
+}
+
+- (NSImage *)addTabButtonPressedImage
+{
+ return _addTabButtonPressedImage;
+}
+
+- (NSImage *)addTabButtonRolloverImage
+{
+ return _addTabButtonRolloverImage;
+}
+
+#pragma mark -
+#pragma mark Cell Specifics
+
+- (NSRect)dragRectForTabCell:(PSMTabBarCell *)cell orientation:(PSMTabBarOrientation)orientation
+{
+ return [cell frame];
+}
+
+- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame
+{
+ if ([cell hasCloseButton] == NO) {
+ return NSZeroRect;
+ }
+
+ NSRect result;
+ result.size = [aquaCloseButton 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 += [aquaCloseButton 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 * kPSMAquaObjectCounterRadius - 6.0);
+ if (countWidth < kPSMAquaCounterMinWidth) {
+ countWidth = kPSMAquaCounterMinWidth;
+ }
+
+ NSRect result;
+ result.size = NSMakeSize(countWidth, 2 * kPSMAquaObjectCounterRadius); // 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 += [aquaCloseButton 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 += [aquaCloseButton 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]);
+
+ [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] 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
+
+- (void)drawTabCell:(PSMTabBarCell *)cell;
+{
+ NSRect cellFrame = [cell frame];
+
+ // Selected Tab
+ if ([cell state] == NSOnState) {
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height-2.5);
+ aRect.size.height -= 0.5;
+
+ // proper tint
+ NSControlTint currentTint;
+ if ([cell controlTint] == NSDefaultControlTint)
+ currentTint = [NSColor currentControlTint];
+ else
+ currentTint = [cell controlTint];
+
+ if (![[[cell controlView] window] isKeyWindow])
+ currentTint = NSClearControlTint;
+
+ NSImage *bgImage;
+ switch (currentTint) {
+ case NSGraphiteControlTint:
+ bgImage = aquaTabBgDownGraphite;
+ break;
+ case NSClearControlTint:
+ bgImage = aquaTabBgDownNonKey;
+ break;
+ case NSBlueControlTint:
+ default:
+ bgImage = aquaTabBgDown;
+ break;
+ }
+
+ [bgImage drawInRect:cellFrame fromRect:NSMakeRect(0.0, 0.0, 1.0, 22.0) operation:NSCompositeSourceOver fraction:1.0];
+ [aquaDivider compositeToPoint:NSMakePoint(cellFrame.origin.x + cellFrame.size.width - 1.0, cellFrame.origin.y + cellFrame.size.height) operation:NSCompositeSourceOver];
+
+ aRect.size.height+=0.5;
+
+ } else { // Unselected Tab
+
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
+ aRect.origin.y += 0.5;
+ aRect.origin.x += 1.5;
+ aRect.size.width -= 1;
+
+ aRect.origin.x -= 1;
+ aRect.size.width += 1;
+
+ // Rollover
+ if ([cell isHighlighted]) {
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
+ NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
+ }
+
+ [aquaDivider compositeToPoint:NSMakePoint(cellFrame.origin.x + cellFrame.size.width - 1.0, cellFrame.origin.y + cellFrame.size.height) operation:NSCompositeSourceOver];
+ }
+
+ [self drawInteriorWithTabCell:cell inView:[cell controlView]];
+}
+
+- (void)drawBackgroundInRect:(NSRect)rect
+{
+ if (rect.size.height <= 22.0) {
+ //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area
+ rect = [tabBar bounds];
+
+ [aquaTabBg drawInRect:rect fromRect:NSMakeRect(0.0, 0.0, 1.0, 22.0) operation:NSCompositeSourceOver fraction:1.0];
+ }
+}
+
+- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
+{
+ 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;
+ while ( (cell = [e nextObject]) ) {
+ if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) {
+ [cell drawWithFrame:[cell frame] inView:bar];
+ }
+ }
+}
+
+- (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]) {
+ NSSize closeButtonSize = NSZeroSize;
+ NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
+ NSImage *closeButton = nil;
+
+ closeButton = [cell isEdited] ? aquaCloseDirtyButton : aquaCloseButton;
+
+ if ([cell closeButtonOver]) closeButton = [cell isEdited] ? aquaCloseDirtyButtonOver : aquaCloseButtonOver;
+ if ([cell closeButtonPressed]) closeButton = [cell isEdited] ? aquaCloseDirtyButtonDown : aquaCloseButtonDown;
+
+ 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 + 1.0;
+
+ if (![[cell indicator] isHidden]) {
+ labelRect.size.width -= (kPSMTabBarIndicatorWidth + kPSMTabBarCellPadding);
+ }
+
+ // object counter
+ if ([cell count] > 0) {
+ [[cell countColor] ?: [NSColor colorWithCalibratedWhite:0.3 alpha:0.45] set];
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ NSRect myRect = [self objectCounterRectForTabCell:cell];
+ [path moveToPoint:NSMakePoint(myRect.origin.x + kPSMAquaObjectCounterRadius, myRect.origin.y)];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMAquaObjectCounterRadius, myRect.origin.y)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMAquaObjectCounterRadius, myRect.origin.y + kPSMAquaObjectCounterRadius) radius:kPSMAquaObjectCounterRadius startAngle:270.0 endAngle:90.0];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + kPSMAquaObjectCounterRadius, myRect.origin.y + myRect.size.height)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMAquaObjectCounterRadius, myRect.origin.y + kPSMAquaObjectCounterRadius) radius:kPSMAquaObjectCounterRadius 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];
+
+ 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:aquaTabBg forKey:@"aquaTabBg"];
+ [aCoder encodeObject:aquaTabBgDown forKey:@"aquaTabBgDown"];
+ [aCoder encodeObject:aquaTabBgDownGraphite forKey:@"aquaTabBgDownGraphite"];
+ [aCoder encodeObject:aquaTabBgDownNonKey forKey:@"aquaTabBgDownNonKey"];
+ [aCoder encodeObject:aquaDividerDown forKey:@"aquaDividerDown"];
+ [aCoder encodeObject:aquaDivider forKey:@"aquaDivider"];
+ [aCoder encodeObject:aquaCloseButton forKey:@"aquaCloseButton"];
+ [aCoder encodeObject:aquaCloseButtonDown forKey:@"aquaCloseButtonDown"];
+ [aCoder encodeObject:aquaCloseButtonOver forKey:@"aquaCloseButtonOver"];
+ [aCoder encodeObject:aquaCloseDirtyButton forKey:@"aquaCloseDirtyButton"];
+ [aCoder encodeObject:aquaCloseDirtyButtonDown forKey:@"aquaCloseDirtyButtonDown"];
+ [aCoder encodeObject:aquaCloseDirtyButtonOver forKey:@"aquaCloseDirtyButtonOver"];
+ [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]) {
+ aquaTabBg = [[aDecoder decodeObjectForKey:@"aquaTabBg"] retain];
+ aquaTabBgDown = [[aDecoder decodeObjectForKey:@"aquaTabBgDown"] retain];
+ aquaTabBgDownGraphite = [[aDecoder decodeObjectForKey:@"aquaTabBgDownGraphite"] retain];
+ aquaTabBgDownNonKey = [[aDecoder decodeObjectForKey:@"aquaTabBgDownNonKey"] retain];
+ aquaDividerDown = [[aDecoder decodeObjectForKey:@"aquaDividerDown"] retain];
+ aquaDivider = [[aDecoder decodeObjectForKey:@"aquaDivider"] retain];
+ aquaCloseButton = [[aDecoder decodeObjectForKey:@"aquaCloseButton"] retain];
+ aquaCloseButtonDown = [[aDecoder decodeObjectForKey:@"aquaCloseButtonDown"] retain];
+ aquaCloseButtonOver = [[aDecoder decodeObjectForKey:@"aquaCloseButtonOver"] retain];
+ aquaCloseDirtyButton = [[aDecoder decodeObjectForKey:@"aquaCloseDirtyButton"] retain];
+ aquaCloseDirtyButtonDown = [[aDecoder decodeObjectForKey:@"aquaCloseDirtyButtonDown"] retain];
+ aquaCloseDirtyButtonOver = [[aDecoder decodeObjectForKey:@"aquaCloseDirtyButtonOver"] retain];
+ _addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain];
+ _addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain];
+ _addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain];
+
+ }
+*/
+ }
+ return self;
+}
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.h
new file mode 100644
index 00000000..b04f83d1
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.h
@@ -0,0 +1,32 @@
+//
+// PSMCardTabStyle.h
+// Fichiers
+//
+// Created by Michael Monscheuer on 05.11.09.
+// Copyright 2009 WriteFlow KG, Wien. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSMTabStyle.h"
+
+@interface PSMCardTabStyle : NSObject <PSMTabStyle>
+{
+ NSImage *unifiedCloseButton;
+ NSImage *unifiedCloseButtonDown;
+ NSImage *unifiedCloseButtonOver;
+ NSImage *unifiedCloseDirtyButton;
+ NSImage *unifiedCloseDirtyButtonDown;
+ NSImage *unifiedCloseDirtyButtonOver;
+ NSImage *_addTabButtonImage;
+ NSImage *_addTabButtonPressedImage;
+ NSImage *_addTabButtonRolloverImage;
+
+ NSDictionary *_objectCountStringAttributes;
+
+ CGFloat leftMargin;
+ PSMTabBarControl *tabBar;
+}
+
+- (void)setLeftMarginForTabBarControl:(CGFloat)margin;
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.m
new file mode 100644
index 00000000..31da000c
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMCardTabStyle.m
@@ -0,0 +1,649 @@
+//
+// PSMCardTabStyle.m
+// Fichiers
+//
+// Created by Michael Monscheuer on 05.11.09.
+// Copyright 2009 WriteFlow KG, Wien. All rights reserved.
+//
+
+#import "PSMCardTabStyle.h"
+#import "PSMTabBarCell.h"
+#import "PSMTabBarControl.h"
+#import "NSBezierPath_AMShading.h"
+
+#define kPSMUnifiedObjectCounterRadius 7.0
+#define kPSMUnifiedCounterMinWidth 20
+
+@interface PSMCardTabStyle (Private)
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
+@end
+
+@implementation PSMCardTabStyle
+
+- (NSString *)name
+{
+ return @"Card";
+}
+
+#pragma mark -
+#pragma mark Creation/Destruction
+
+- (id) init
+{
+ if ( (self = [super init]) ) {
+ unifiedCloseButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front"]];
+ unifiedCloseButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Pressed"]];
+ unifiedCloseButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Rollover"]];
+
+ unifiedCloseDirtyButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front"]];
+ unifiedCloseDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Pressed"]];
+ unifiedCloseDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Rollover"]];
+
+ _addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNew"]];
+ _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewPressed"]];
+ _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewRollover"]];
+
+ _objectCountStringAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSFontManager sharedFontManager] convertFont:[NSFont fontWithName:@"Helvetica" size:11.0] toHaveTrait:NSBoldFontMask], NSFontAttributeName,
+ [[NSColor whiteColor] colorWithAlphaComponent:0.85], NSForegroundColorAttributeName,
+ nil, nil];
+
+ leftMargin = 5.0;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [unifiedCloseButton release];
+ [unifiedCloseButtonDown release];
+ [unifiedCloseButtonOver release];
+ [unifiedCloseDirtyButton release];
+ [unifiedCloseDirtyButtonDown release];
+ [unifiedCloseDirtyButtonOver release];
+ [_addTabButtonImage release];
+ [_addTabButtonPressedImage release];
+ [_addTabButtonRolloverImage release];
+
+ [_objectCountStringAttributes release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Control Specific
+
+- (void)setLeftMarginForTabBarControl:(CGFloat)margin
+{
+ leftMargin = margin;
+}
+
+- (CGFloat)leftMarginForTabBarControl
+{
+ return leftMargin;
+}
+
+- (CGFloat)rightMarginForTabBarControl
+{
+ return 5.0f;
+// return 24.0f;
+}
+
+- (CGFloat)topMarginForTabBarControl
+{
+ return 10.0f;
+}
+
+- (void)setOrientation:(PSMTabBarOrientation)value
+{
+
+}
+
+#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)orientation
+{
+ NSRect dragRect = [cell frame];
+ dragRect.size.width++;
+ return dragRect;
+}
+
+- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame
+{
+ if ([cell hasCloseButton] == NO || [cell isCloseButtonSuppressed]) {
+ return NSZeroRect;
+ }
+
+ NSRect result;
+ result.size = [unifiedCloseButton size];
+ result.origin.x = cellFrame.origin.x + MARGIN_X;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.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 - 1.0;
+
+ if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) {
+ result.origin.x += [unifiedCloseButton 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 - 1.0;
+
+ 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 * kPSMUnifiedObjectCounterRadius - 6.0);
+ if (countWidth < kPSMUnifiedCounterMinWidth) {
+ countWidth = kPSMUnifiedCounterMinWidth;
+ }
+
+ NSRect result;
+ result.size = NSMakeSize(countWidth, 2 * kPSMUnifiedObjectCounterRadius); // 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 += [unifiedCloseButton 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 += [unifiedCloseButton 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]);
+
+ [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] range:range];
+
+ // Paragraph Style for Truncating Long Text
+ static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil;
+ if (!TruncatingTailParagraphStyle) {
+ TruncatingTailParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain];
+ [TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
+ }
+ [attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range];
+
+ return attrStr;
+}
+
+#pragma mark -
+#pragma mark ---- drawing ----
+
+- (void)drawTabCell:(PSMTabBarCell *)cell
+{
+ NSRect cellFrame = [cell frame];
+ BOOL showsBaselineSeparator = NO;
+/*
+ NSToolbar *toolbar = [[[cell controlView] window] toolbar];
+ BOOL showsBaselineSeparator = (toolbar && [toolbar respondsToSelector:@selector(showsBaselineSeparator)] && [toolbar showsBaselineSeparator]);
+*/
+ if (!showsBaselineSeparator) {
+ cellFrame.origin.y += 3.0;
+ cellFrame.size.height -= 3.0;
+ }
+
+
+ NSColor * lineColor = nil;
+ NSBezierPath* bezier = [NSBezierPath bezierPath];
+ lineColor = [NSColor colorWithCalibratedWhite:0.576 alpha:1.0];
+
+ if (!showsBaselineSeparator || [cell state] == NSOnState)
+ {
+// // selected tab
+// NSRect aRect = NSMakeRect(cellFrame.origin.x+0.5, cellFrame.origin.y-0.5, cellFrame.size.width, cellFrame.size.height);
+ // selected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x+.5, cellFrame.origin.y+0.5, cellFrame.size.width-1.0, cellFrame.size.height-1.0);
+
+ // frame
+ CGFloat radius = MIN(6.0, 0.5f * MIN(NSWidth(aRect), NSHeight(aRect)))-0.5;
+// NSRect rect = NSInsetRect(aRect, radius, radius);
+
+ [bezier moveToPoint: NSMakePoint(NSMinX(aRect),NSMaxY(aRect))];
+ [bezier appendBezierPathWithArcFromPoint:NSMakePoint(NSMinX(aRect),NSMinY(aRect)) toPoint:NSMakePoint(NSMidX(aRect),NSMinY(aRect)) radius:radius];
+ [bezier appendBezierPathWithArcFromPoint:NSMakePoint(NSMaxX(aRect),NSMinY(aRect)) toPoint:NSMakePoint(NSMaxX(aRect),NSMaxY(aRect)) radius:radius];
+ [bezier lineToPoint: NSMakePoint(NSMaxX(aRect),NSMaxY(aRect))];
+
+/*
+ [bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMinY(rect)) radius:radius startAngle:180.0 endAngle:270.0];
+
+ [bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMinY(rect)) radius:radius startAngle:270.0 endAngle:360.0];
+
+ NSPoint cornerPoint = NSMakePoint(NSMaxX(aRect), NSMaxY(aRect));
+ [bezier appendBezierPathWithPoints:&cornerPoint count:1];
+
+ cornerPoint = NSMakePoint(NSMinX(aRect), NSMaxY(aRect));
+ [bezier appendBezierPathWithPoints:&cornerPoint count:1];
+
+ [bezier closePath];
+*/
+
+ //[[NSColor windowBackgroundColor] set];
+ //[bezier fill];
+ if ([NSApp isActive]) {
+ if ([cell state] == NSOnState) {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.99 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.941 alpha:1.0]];
+ } else if ([cell isHighlighted]) {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.80 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.80 alpha:1.0]];
+ } else {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ }
+ }
+
+ [lineColor set];
+ [bezier stroke];
+
+ }
+ else
+ {
+ // unselected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
+ aRect.origin.y += 0.5;
+ aRect.origin.x += 1.5;
+ aRect.size.width -= 1;
+
+ aRect.origin.x -= 1;
+ aRect.size.width += 1;
+
+ // rollover
+ if ([cell isHighlighted])
+ {
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
+ NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
+ }
+
+ // frame
+
+ [lineColor set];
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y-0.5)];
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
+ }
+
+ [bezier stroke];
+
+ // Create a thin lighter line next to the dividing line for a bezel effect
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [[[NSColor redColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(aRect)+1.0, aRect.origin.y-0.5)
+ toPoint:NSMakePoint(NSMaxX(aRect)+1.0, NSMaxY(aRect)-2.5)];
+ }
+
+ // If this is the leftmost tab, we want to draw a line on the left, too
+ if ([cell tabState] & PSMTab_PositionLeftMask)
+ {
+ [lineColor set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x,aRect.origin.y-0.5)
+ toPoint:NSMakePoint(aRect.origin.x,NSMaxY(aRect)-2.5)];
+ [[[NSColor redColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x+1.0,aRect.origin.y-0.5)
+ toPoint:NSMakePoint(aRect.origin.x+1.0,NSMaxY(aRect)-2.5)];
+ }
+ }
+
+ [self drawInteriorWithTabCell:cell inView:[cell controlView]];
+}
+
+
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView
+{
+ NSRect cellFrame = [cell frame];
+
+ BOOL showsBaselineSeparator = NO;
+/*
+ NSToolbar *toolbar = [[[cell controlView] window] toolbar];
+ BOOL showsBaselineSeparator = (toolbar && [toolbar respondsToSelector:@selector(showsBaselineSeparator)] && [toolbar showsBaselineSeparator]);
+*/
+ if (!showsBaselineSeparator) {
+ cellFrame.origin.y += 3.0;
+ cellFrame.size.height -= 3.0;
+ }
+
+ CGFloat labelPosition = cellFrame.origin.x + MARGIN_X;
+
+ // close button
+ if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) {
+ NSSize closeButtonSize = NSZeroSize;
+ NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
+ NSImage * closeButton = nil;
+
+ closeButton = [cell isEdited] ? unifiedCloseDirtyButton : unifiedCloseButton;
+
+ if ([cell closeButtonOver]) closeButton = [cell isEdited] ? unifiedCloseDirtyButtonOver : unifiedCloseButtonOver;
+ if ([cell closeButtonPressed]) closeButton = [cell isEdited] ? unifiedCloseDirtyButtonDown : unifiedCloseButtonDown;
+
+ 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;
+ NSSize s = [[cell attributedStringValue] size];
+ labelRect.origin.y = cellFrame.origin.y + (cellFrame.size.height-s.height)/2 + 1;
+ labelRect.size.height = s.height;
+
+ 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];
+ myRect.origin.y -= 1.0;
+ [path moveToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius startAngle:270.0 endAngle:90.0];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + myRect.size.height)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius 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];
+
+ labelRect.size.width -= myRect.size.width + kPSMTabBarCellPadding;
+ }
+
+ // label
+ [[cell attributedStringValue] drawInRect:labelRect];
+}
+
+- (void)drawBackgroundInRect:(NSRect)rect
+{
+ //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area
+ rect = [tabBar bounds];
+
+ NSRect gradientRect = rect;
+ gradientRect.size.height -= 1.0;
+
+ NSBezierPath *path = [NSBezierPath bezierPathWithRect:gradientRect];
+ [path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ [[NSColor colorWithCalibratedWhite:0.576 alpha:1.0] set];
+
+
+ if (![[[tabBar tabView] window] isKeyWindow]) {
+ [[NSColor windowBackgroundColor] set];
+ NSRectFill(gradientRect);
+ }
+}
+
+- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
+{
+ [NSGraphicsContext saveGraphicsState];
+
+ // draw button separator
+ for(PSMTabBarCell *cell in [bar cells])
+ {
+ if([cell state] == NSOnState)
+ {
+ [[NSColor colorWithCalibratedWhite:0.576 alpha:1.0] set];
+
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x,NSMaxY(rect)-0.5)
+ toPoint:NSMakePoint(NSMinX([cell frame]),NSMaxY(rect)-0.5)];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX([cell frame]),NSMaxY(rect)-0.5)
+ toPoint:NSMakePoint(NSMaxX(rect),NSMaxY(rect)-0.5)];
+ }
+ }
+
+ 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];
+ [centeredParagraphStyle setAlignment:NSCenterTextAlignment];
+ }
+ [attrStr addAttribute:NSParagraphStyleAttributeName value:centeredParagraphStyle range:range];
+ [centeredParagraphStyle release];
+ [attrStr drawInRect:labelRect];
+
+ goto EXIT;
+ }
+
+ // draw cells
+ NSEnumerator *e = [[bar cells] objectEnumerator];
+ PSMTabBarCell *cell;
+ while ( (cell = [e nextObject]) ) {
+ if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) {
+ [cell drawWithFrame:[cell frame] inView:bar];
+ }
+ }
+
+EXIT:
+ [NSGraphicsContext restoreGraphicsState];
+
+}
+
+#pragma mark -
+#pragma mark Archiving
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+/*
+ //[super encodeWithCoder:aCoder];
+ if ([aCoder allowsKeyedCoding]) {
+ [aCoder encodeObject:unifiedCloseButton forKey:@"unifiedCloseButton"];
+ [aCoder encodeObject:unifiedCloseButtonDown forKey:@"unifiedCloseButtonDown"];
+ [aCoder encodeObject:unifiedCloseButtonOver forKey:@"unifiedCloseButtonOver"];
+ [aCoder encodeObject:unifiedCloseDirtyButton forKey:@"unifiedCloseDirtyButton"];
+ [aCoder encodeObject:unifiedCloseDirtyButtonDown forKey:@"unifiedCloseDirtyButtonDown"];
+ [aCoder encodeObject:unifiedCloseDirtyButtonOver forKey:@"unifiedCloseDirtyButtonOver"];
+ [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]) {
+ unifiedCloseButton = [[aDecoder decodeObjectForKey:@"unifiedCloseButton"] retain];
+ unifiedCloseButtonDown = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonDown"] retain];
+ unifiedCloseButtonOver = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonOver"] retain];
+ unifiedCloseDirtyButton = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButton"] retain];
+ unifiedCloseDirtyButtonDown = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButtonDown"] retain];
+ unifiedCloseDirtyButtonOver = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButtonOver"] retain];
+ _addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain];
+ _addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain];
+ _addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain];
+ }
+ */
+ }
+ return self;
+}
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.h
new file mode 100644
index 00000000..22cb7bc8
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.h
@@ -0,0 +1,34 @@
+//
+// PSMMetalTabStyle.h
+// PSMTabBarControl
+//
+// Created by John Pannell on 2/17/06.
+// Copyright 2006 Positive Spin Media. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSMTabStyle.h"
+
+@interface PSMMetalTabStyle : NSObject <PSMTabStyle> {
+ NSImage *metalCloseButton;
+ NSImage *metalCloseButtonDown;
+ NSImage *metalCloseButtonOver;
+ NSImage *metalCloseDirtyButton;
+ NSImage *metalCloseDirtyButtonDown;
+ NSImage *metalCloseDirtyButtonOver;
+ NSImage *_addTabButtonImage;
+ NSImage *_addTabButtonPressedImage;
+ NSImage *_addTabButtonRolloverImage;
+
+ NSDictionary *_objectCountStringAttributes;
+
+ PSMTabBarOrientation orientation;
+ PSMTabBarControl *tabBar;
+}
+
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
+
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+- (id)initWithCoder:(NSCoder *)aDecoder;
+
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.m
new file mode 100644
index 00000000..443179ce
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMMetalTabStyle.m
@@ -0,0 +1,656 @@
+//
+// PSMMetalTabStyle.m
+// PSMTabBarControl
+//
+// Created by John Pannell on 2/17/06.
+// Copyright 2006 Positive Spin Media. All rights reserved.
+//
+
+#import "PSMMetalTabStyle.h"
+#import "PSMTabBarCell.h"
+#import "PSMTabBarControl.h"
+
+#define kPSMMetalObjectCounterRadius 7.0
+#define kPSMMetalCounterMinWidth 20
+
+@implementation PSMMetalTabStyle
+
+- (NSString *)name
+{
+ return @"Metal";
+}
+
+#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:@"TabNewMetal"]];
+ _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabNewMetalPressed"]];
+ _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"TabNewMetalRollover"]];
+
+ _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 10.0f;
+}
+
+- (CGFloat)rightMarginForTabBarControl
+{
+ return 24.0f;
+}
+
+- (CGFloat)topMarginForTabBarControl
+{
+ return 10.0f;
+}
+
+- (void)setOrientation:(PSMTabBarOrientation)value
+{
+ orientation = value;
+}
+
+#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;
+
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+
+ 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;
+ }
+
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+
+ 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;
+
+ if ([cell state] == NSOnState) {
+ result.origin.y -= 1;
+ }
+
+ 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 ----
+
+- (void)drawTabCell:(PSMTabBarCell *)cell
+{
+ NSRect cellFrame = [cell frame];
+ NSColor *lineColor = nil;
+ NSBezierPath *bezier = [NSBezierPath bezierPath];
+ lineColor = [NSColor darkGrayColor];
+
+ //disable antialiasing of bezier paths
+ [NSGraphicsContext saveGraphicsState];
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ if ([cell state] == NSOnState) {
+ // selected tab
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height-2.5);
+
+ // background
+ aRect.origin.x += 1.0;
+ aRect.size.width--;
+ aRect.size.height -= 0.5;
+ NSDrawWindowBackground(aRect);
+ aRect.size.width++;
+ aRect.size.height += 0.5;
+
+ // frame
+ aRect.origin.x -= 0.5;
+ [lineColor set];
+ [bezier setLineWidth:1.0];
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y+aRect.size.height-1.5)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+1.5, aRect.origin.y+aRect.size.height)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+aRect.size.width-2.5, aRect.origin.y+aRect.size.height)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+aRect.size.width, aRect.origin.y+aRect.size.height-1.5)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+aRect.size.width, aRect.origin.y)];
+ if ([[cell controlView] frame].size.height < 2) {
+ // special case of hidden control; need line across top of cell
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y+0.5)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x+aRect.size.width, aRect.origin.y+0.5)];
+ }
+ } else {
+ NSRect aRect = NSMakeRect(cellFrame.origin.x + 2, cellFrame.origin.y, cellFrame.size.width - 2, cellFrame.size.height);
+
+ // background
+ aRect.origin.x++;
+ aRect.size.height--;
+ NSDrawWindowBackground(aRect);
+ aRect.origin.x--;
+ aRect.size.height++;
+
+ // frame
+ [lineColor set];
+ [bezier setLineWidth:1.0];
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + 2, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + 0.5, aRect.origin.y + 2)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + 0.5, aRect.origin.y + aRect.size.height - 3)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + 3, aRect.origin.y + aRect.size.height)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + aRect.size.height)];
+ }
+
+ [bezier stroke];
+ } else {
+
+ // unselected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
+ aRect.origin.y += 0.5;
+ aRect.origin.x += 1.5;
+ aRect.size.width -= 1;
+
+ // rollover
+ if ([cell isHighlighted]) {
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
+ NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
+ }
+
+ [lineColor set];
+
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ aRect.origin.x -= 1;
+ aRect.size.width += 1;
+
+ // frame
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y)];
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + aRect.size.height)];
+ }
+ } else {
+ if (!([cell tabState] & PSMTab_LeftIsSelectedMask)) {
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y)];
+ }
+
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x, aRect.origin.y + aRect.size.height)];
+ [bezier lineToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y + aRect.size.height)];
+ }
+ }
+ [bezier stroke];
+ }
+
+ [NSGraphicsContext restoreGraphicsState];
+
+ [self drawInteriorWithTabCell:cell inView:[cell controlView]];
+}
+
+
+- (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]) {
+ NSSize closeButtonSize = NSZeroSize;
+ NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
+ NSImage * closeButton = nil;
+
+ 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 + 1.0;
+
+ 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];
+}
+
+- (void)drawBackgroundInRect:(NSRect)rect
+{
+ //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area
+ rect = [tabBar bounds];
+
+ if (orientation == PSMTabBarVerticalOrientation && [tabBar frame].size.width < 2) {
+ return;
+ }
+
+ [NSGraphicsContext saveGraphicsState];
+ [[NSGraphicsContext currentContext] setShouldAntialias:NO];
+
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set];
+ NSRectFillUsingOperation(rect, NSCompositeSourceAtop);
+ [[NSColor darkGrayColor] set];
+
+ if (orientation == PSMTabBarHorizontalOrientation) {
+ [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 {
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, rect.origin.y + 0.5) toPoint:NSMakePoint(rect.origin.x, rect.origin.y + rect.size.height + 0.5)];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + 0.5) toPoint:NSMakePoint(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height + 0.5)];
+ }
+
+ [NSGraphicsContext restoreGraphicsState];
+}
+
+- (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;
+ while ( (cell = [e nextObject]) ) {
+ if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) {
+ [cell drawWithFrame:[cell frame] inView:bar];
+ }
+ }
+}
+
+#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/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.h b/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.h
new file mode 100644
index 00000000..d44bbcdc
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.h
@@ -0,0 +1,30 @@
+//
+// PSMUnifiedTabStyle.h
+// --------------------
+//
+// Created by Keith Blount on 30/04/2006.
+// Copyright 2006 __MyCompanyName__. All rights reserved.
+//
+
+#import <Cocoa/Cocoa.h>
+#import "PSMTabStyle.h"
+
+@interface PSMUnifiedTabStyle : NSObject <PSMTabStyle>
+{
+ NSImage *unifiedCloseButton;
+ NSImage *unifiedCloseButtonDown;
+ NSImage *unifiedCloseButtonOver;
+ NSImage *unifiedCloseDirtyButton;
+ NSImage *unifiedCloseDirtyButtonDown;
+ NSImage *unifiedCloseDirtyButtonOver;
+ NSImage *_addTabButtonImage;
+ NSImage *_addTabButtonPressedImage;
+ NSImage *_addTabButtonRolloverImage;
+
+ NSDictionary *_objectCountStringAttributes;
+
+ CGFloat leftMargin;
+ PSMTabBarControl *tabBar;
+}
+- (void)setLeftMarginForTabBarControl:(CGFloat)margin;
+@end
diff --git a/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.m b/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.m
new file mode 100644
index 00000000..13fb0994
--- /dev/null
+++ b/Frameworks/PSMTabBar/Styles/PSMUnifiedTabStyle.m
@@ -0,0 +1,603 @@
+//
+// PSMUnifiedTabStyle.m
+// --------------------
+//
+// Created by Keith Blount on 30/04/2006.
+// Copyright 2006 __MyCompanyName__. All rights reserved.
+//
+
+#import "PSMUnifiedTabStyle.h"
+#import "PSMTabBarCell.h"
+#import "PSMTabBarControl.h"
+#import "NSBezierPath_AMShading.h"
+
+#define kPSMUnifiedObjectCounterRadius 7.0
+#define kPSMUnifiedCounterMinWidth 20
+
+@interface PSMUnifiedTabStyle (Private)
+- (void)drawInteriorWithTabCell:(PSMTabBarCell *)cell inView:(NSView*)controlView;
+@end
+
+@implementation PSMUnifiedTabStyle
+
+- (NSString *)name
+{
+ return @"Unified";
+}
+
+#pragma mark -
+#pragma mark Creation/Destruction
+
+- (id) init
+{
+ if ( (self = [super init]) ) {
+ unifiedCloseButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front"]];
+ unifiedCloseButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Pressed"]];
+ unifiedCloseButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabClose_Front_Rollover"]];
+
+ unifiedCloseDirtyButton = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front"]];
+ unifiedCloseDirtyButtonDown = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Pressed"]];
+ unifiedCloseDirtyButtonOver = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabCloseDirty_Front_Rollover"]];
+
+ _addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNew"]];
+ _addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewPressed"]];
+ _addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewRollover"]];
+
+ _objectCountStringAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:[[NSFontManager sharedFontManager] convertFont:[NSFont fontWithName:@"Helvetica" size:11.0] toHaveTrait:NSBoldFontMask], NSFontAttributeName,
+ [[NSColor whiteColor] colorWithAlphaComponent:0.85], NSForegroundColorAttributeName,
+ nil, nil];
+
+ leftMargin = 5.0;
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [unifiedCloseButton release];
+ [unifiedCloseButtonDown release];
+ [unifiedCloseButtonOver release];
+ [unifiedCloseDirtyButton release];
+ [unifiedCloseDirtyButtonDown release];
+ [unifiedCloseDirtyButtonOver release];
+ [_addTabButtonImage release];
+ [_addTabButtonPressedImage release];
+ [_addTabButtonRolloverImage release];
+
+ [_objectCountStringAttributes release];
+
+ [super dealloc];
+}
+
+#pragma mark -
+#pragma mark Control Specific
+
+- (void)setLeftMarginForTabBarControl:(CGFloat)margin
+{
+ leftMargin = margin;
+}
+
+- (CGFloat)leftMarginForTabBarControl
+{
+ return leftMargin;
+}
+
+- (CGFloat)rightMarginForTabBarControl
+{
+ return 24.0f;
+}
+
+- (CGFloat)topMarginForTabBarControl
+{
+ return 10.0f;
+}
+
+- (void)setOrientation:(PSMTabBarOrientation)value
+{
+
+}
+
+#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)orientation
+{
+ NSRect dragRect = [cell frame];
+ dragRect.size.width++;
+ return dragRect;
+}
+
+- (NSRect)closeButtonRectForTabCell:(PSMTabBarCell *)cell withFrame:(NSRect)cellFrame
+{
+ if ([cell hasCloseButton] == NO) {
+ return NSZeroRect;
+ }
+
+ NSRect result;
+ result.size = [unifiedCloseButton size];
+ result.origin.x = cellFrame.origin.x + MARGIN_X;
+ result.origin.y = cellFrame.origin.y + MARGIN_Y + 1.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 - 1.0;
+
+ if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) {
+ result.origin.x += [unifiedCloseButton 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 - 1.0;
+
+ 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 * kPSMUnifiedObjectCounterRadius - 6.0);
+ if (countWidth < kPSMUnifiedCounterMinWidth) {
+ countWidth = kPSMUnifiedCounterMinWidth;
+ }
+
+ NSRect result;
+ result.size = NSMakeSize(countWidth, 2 * kPSMUnifiedObjectCounterRadius); // 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 += [unifiedCloseButton 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 += [unifiedCloseButton 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]);
+
+ [attrStr addAttribute:NSFontAttributeName value:[NSFont systemFontOfSize:11.0] range:range];
+
+ // Paragraph Style for Truncating Long Text
+ static NSMutableParagraphStyle *TruncatingTailParagraphStyle = nil;
+ if (!TruncatingTailParagraphStyle) {
+ TruncatingTailParagraphStyle = [[[NSParagraphStyle defaultParagraphStyle] mutableCopy] retain];
+ [TruncatingTailParagraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
+ }
+ [attrStr addAttribute:NSParagraphStyleAttributeName value:TruncatingTailParagraphStyle range:range];
+
+ return attrStr;
+}
+
+#pragma mark -
+#pragma mark ---- drawing ----
+
+- (void)drawTabCell:(PSMTabBarCell *)cell
+{
+ NSRect cellFrame = [cell frame];
+
+ NSToolbar *toolbar = [[[cell controlView] window] toolbar];
+ BOOL showsBaselineSeparator = (toolbar && [toolbar respondsToSelector:@selector(showsBaselineSeparator)] && [toolbar showsBaselineSeparator]);
+ if (!showsBaselineSeparator) {
+ cellFrame.origin.y += 1.0;
+ cellFrame.size.height -= 1.0;
+ }
+
+ NSColor * lineColor = nil;
+ NSBezierPath* bezier = [NSBezierPath bezierPath];
+ lineColor = [NSColor colorWithCalibratedWhite:0.576 alpha:1.0];
+
+ if (!showsBaselineSeparator || [cell state] == NSOnState)
+ {
+ // selected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x+0.5, cellFrame.origin.y-0.5, cellFrame.size.width, cellFrame.size.height);
+
+ // frame
+ CGFloat radius = MIN(6.0, 0.5f * MIN(NSWidth(aRect), NSHeight(aRect)));
+ NSRect rect = NSInsetRect(aRect, radius, radius);
+
+ [bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMinX(rect), NSMinY(rect)) radius:radius startAngle:180.0 endAngle:270.0];
+
+ [bezier appendBezierPathWithArcWithCenter:NSMakePoint(NSMaxX(rect), NSMinY(rect)) radius:radius startAngle:270.0 endAngle:360.0];
+
+ NSPoint cornerPoint = NSMakePoint(NSMaxX(aRect), NSMaxY(aRect));
+ [bezier appendBezierPathWithPoints:&cornerPoint count:1];
+
+ cornerPoint = NSMakePoint(NSMinX(aRect), NSMaxY(aRect));
+ [bezier appendBezierPathWithPoints:&cornerPoint count:1];
+
+ [bezier closePath];
+
+ //[[NSColor windowBackgroundColor] set];
+ //[bezier fill];
+ if ([NSApp isActive]) {
+ if ([cell state] == NSOnState) {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.99 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.941 alpha:1.0]];
+ } else if ([cell isHighlighted]) {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.80 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.80 alpha:1.0]];
+ } else {
+ [bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ }
+ }
+
+ [lineColor set];
+ [bezier stroke];
+ }
+ else
+ {
+ // unselected tab
+ NSRect aRect = NSMakeRect(cellFrame.origin.x, cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
+ aRect.origin.y += 0.5;
+ aRect.origin.x += 1.5;
+ aRect.size.width -= 1;
+
+ aRect.origin.x -= 1;
+ aRect.size.width += 1;
+
+ // rollover
+ if ([cell isHighlighted])
+ {
+ [[NSColor colorWithCalibratedWhite:0.0 alpha:0.1] set];
+ NSRectFillUsingOperation(aRect, NSCompositeSourceAtop);
+ }
+
+ // frame
+
+ [lineColor set];
+ [bezier moveToPoint:NSMakePoint(aRect.origin.x + aRect.size.width, aRect.origin.y-0.5)];
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [bezier lineToPoint:NSMakePoint(NSMaxX(aRect), NSMaxY(aRect))];
+ }
+
+ [bezier stroke];
+
+ // Create a thin lighter line next to the dividing line for a bezel effect
+ if (!([cell tabState] & PSMTab_RightIsSelectedMask)) {
+ [[[NSColor whiteColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(NSMaxX(aRect)+1.0, aRect.origin.y-0.5)
+ toPoint:NSMakePoint(NSMaxX(aRect)+1.0, NSMaxY(aRect)-2.5)];
+ }
+
+ // If this is the leftmost tab, we want to draw a line on the left, too
+ if ([cell tabState] & PSMTab_PositionLeftMask)
+ {
+ [lineColor set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x,aRect.origin.y-0.5)
+ toPoint:NSMakePoint(aRect.origin.x,NSMaxY(aRect)-2.5)];
+ [[[NSColor whiteColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(aRect.origin.x+1.0,aRect.origin.y-0.5)
+ toPoint:NSMakePoint(aRect.origin.x+1.0,NSMaxY(aRect)-2.5)];
+ }
+ }
+
+ [self drawInteriorWithTabCell:cell inView:[cell controlView]];
+}
+
+
+- (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]) {
+ NSSize closeButtonSize = NSZeroSize;
+ NSRect closeButtonRect = [cell closeButtonRectForFrame:cellFrame];
+ NSImage * closeButton = nil;
+
+ closeButton = [cell isEdited] ? unifiedCloseDirtyButton : unifiedCloseButton;
+
+ if ([cell closeButtonOver]) closeButton = [cell isEdited] ? unifiedCloseDirtyButtonOver : unifiedCloseButtonOver;
+ if ([cell closeButtonPressed]) closeButton = [cell isEdited] ? unifiedCloseDirtyButtonDown : unifiedCloseButtonDown;
+
+ 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;
+ NSSize s = [[cell attributedStringValue] size];
+ labelRect.origin.y = cellFrame.origin.y + (cellFrame.size.height-s.height) / 2.0 - 1.0;
+ labelRect.size.height = s.height;
+
+ 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];
+ myRect.origin.y -= 1.0;
+ [path moveToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + myRect.size.width - kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius startAngle:270.0 endAngle:90.0];
+ [path lineToPoint:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + myRect.size.height)];
+ [path appendBezierPathWithArcWithCenter:NSMakePoint(myRect.origin.x + kPSMUnifiedObjectCounterRadius, myRect.origin.y + kPSMUnifiedObjectCounterRadius) radius:kPSMUnifiedObjectCounterRadius 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];
+
+ labelRect.size.width -= myRect.size.width + kPSMTabBarCellPadding;
+ }
+
+ // label
+ [[cell attributedStringValue] drawInRect:labelRect];
+}
+
+- (void)drawBackgroundInRect:(NSRect)rect
+{
+ //Draw for our whole bounds; it'll be automatically clipped to fit the appropriate drawing area
+ rect = [tabBar bounds];
+
+ NSRect gradientRect = rect;
+ gradientRect.size.height -= 1.0;
+
+ NSBezierPath *path = [NSBezierPath bezierPathWithRect:gradientRect];
+ [path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.835 alpha:1.0]
+ endColor:[NSColor colorWithCalibratedWhite:0.843 alpha:1.0]];
+ [[NSColor colorWithCalibratedWhite:0.576 alpha:1.0] set];
+ [NSBezierPath strokeLineFromPoint:NSMakePoint(rect.origin.x, NSMaxY(rect) - 0.5)
+ toPoint:NSMakePoint(NSMaxX(rect), NSMaxY(rect) - 0.5)];
+
+ if (![[[tabBar tabView] window] isKeyWindow]) {
+ [[NSColor windowBackgroundColor] set];
+ NSRectFill(gradientRect);
+ }
+}
+
+- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
+{
+ 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;
+ while ( (cell = [e nextObject]) ) {
+ if ([bar isAnimating] || (![cell isInOverflowMenu] && NSIntersectsRect([cell frame], rect))) {
+ [cell drawWithFrame:[cell frame] inView:bar];
+ }
+ }
+}
+
+#pragma mark -
+#pragma mark Archiving
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+/*
+ //[super encodeWithCoder:aCoder];
+ if ([aCoder allowsKeyedCoding]) {
+ [aCoder encodeObject:unifiedCloseButton forKey:@"unifiedCloseButton"];
+ [aCoder encodeObject:unifiedCloseButtonDown forKey:@"unifiedCloseButtonDown"];
+ [aCoder encodeObject:unifiedCloseButtonOver forKey:@"unifiedCloseButtonOver"];
+ [aCoder encodeObject:unifiedCloseDirtyButton forKey:@"unifiedCloseDirtyButton"];
+ [aCoder encodeObject:unifiedCloseDirtyButtonDown forKey:@"unifiedCloseDirtyButtonDown"];
+ [aCoder encodeObject:unifiedCloseDirtyButtonOver forKey:@"unifiedCloseDirtyButtonOver"];
+ [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]) {
+ unifiedCloseButton = [[aDecoder decodeObjectForKey:@"unifiedCloseButton"] retain];
+ unifiedCloseButtonDown = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonDown"] retain];
+ unifiedCloseButtonOver = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonOver"] retain];
+ unifiedCloseDirtyButton = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButton"] retain];
+ unifiedCloseDirtyButtonDown = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButtonDown"] retain];
+ unifiedCloseDirtyButtonOver = [[aDecoder decodeObjectForKey:@"unifiedCloseDirtyButtonOver"] retain];
+ _addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain];
+ _addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain];
+ _addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain];
+ }
+ */
+ }
+ return self;
+}
+
+@end