Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

527 lines (418 sloc) 18.857 kb
//
// 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"]];
_addTabButtonImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNew"]];
_addTabButtonPressedImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewPressed"]];
_addTabButtonRolloverImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"AquaTabNewRollover"]];
leftMargin = 5.0;
}
return self;
}
- (void)dealloc
{
[unifiedCloseButton release];
[unifiedCloseButtonDown release];
[unifiedCloseButtonOver release];
[_addTabButtonImage release];
[_addTabButtonPressedImage release];
[_addTabButtonRolloverImage release];
[truncatingTailParagraphStyle release];
[centeredParagraphStyle release];
[super dealloc];
}
#pragma mark -
#pragma mark Control Specific
- (void)setLeftMarginForTabBarControl:(float)margin
{
leftMargin = margin;
}
- (float)leftMarginForTabBarControl
{
return leftMargin;
}
- (float)rightMarginForTabBarControl
{
return 24.0f;
}
#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) closeButtonRectForTabCell:(PSMTabBarCell *)cell
{
NSRect cellFrame = [cell frame];
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;
}
float 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;
}
- (float)minimumWidthOfTabCell:(PSMTabBarCell *)cell
{
float 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);
}
- (float)desiredWidthOfTabCell:(PSMTabBarCell *)cell
{
float 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);
}
#pragma mark -
#pragma mark Cell Values
- (NSAttributedString *)attributedObjectCountValueForTabCell:(PSMTabBarCell *)cell
{
NSMutableAttributedString *attrStr;
NSFontManager *fm = [NSFontManager sharedFontManager];
NSNumberFormatter *nf = [[[NSNumberFormatter alloc] init] autorelease];
[nf setLocalizesFormat:YES];
[nf setFormat:@"0"];
[nf setHasThousandSeparators:YES];
NSString *contents = [nf stringFromNumber:[NSNumber numberWithInt:[cell count]]];
attrStr = [[[NSMutableAttributedString alloc] initWithString:contents] autorelease];
NSRange range = NSMakeRange(0, [contents length]);
// Add font attribute
[attrStr addAttribute:NSFontAttributeName value:[fm convertFont:[NSFont fontWithName:@"Helvetica" size:11.0] toHaveTrait:NSBoldFontMask] range:range];
[attrStr addAttribute:NSForegroundColorAttributeName value:[[NSColor whiteColor] colorWithAlphaComponent:0.85] range:range];
return attrStr;
}
- (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
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];
NSColor * lineColor = nil;
NSBezierPath* bezier = [NSBezierPath bezierPath];
lineColor = [NSColor colorWithCalibratedWhite:0.576 alpha:1.0];
if ([cell state] == NSOnState)
{
// selected tab
NSRect aRect = NSMakeRect(cellFrame.origin.x+0.5, cellFrame.origin.y-0.5, cellFrame.size.width-1.0, cellFrame.size.height);
aRect.size.height -= 0.5;
aRect.size.height+=0.5;
// frame
float 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];
[bezier linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.99 alpha:1.0]
endColor:[NSColor colorWithCalibratedWhite:0.941 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];
float 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 = unifiedCloseButton;
if ([cell closeButtonOver]) closeButton = unifiedCloseButtonOver;
if ([cell closeButtonPressed]) closeButton = unifiedCloseButtonDown;
closeButtonSize = [closeButton size];
[closeButton setFlipped:YES];
[closeButton drawAtPoint:closeButtonRect.origin fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
// scoot label over
labelPosition += closeButtonSize.width + kPSMTabBarCellPadding;
}
#if 0 // MacVim: disable this code. It is unused and calling 'content' on the represented object's identifier seems dangerous at best.
// icon
if([cell hasIcon]){
NSRect iconRect = [self iconRectForTabCell:cell];
NSImage *icon = [[[[cell representedObject] identifier] content] icon];
if ([controlView isFlipped]) {
iconRect.origin.y = cellFrame.size.height - iconRect.origin.y;
}
[icon compositeToPoint:iconRect.origin operation:NSCompositeSourceOver fraction:1.0];
// scoot label over
labelPosition += iconRect.size.width + kPSMTabBarCellPadding;
}
#endif
// object counter
if([cell count] > 0){
[[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];
}
// 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);
if([cell count] > 0)
labelRect.size.width -= ([self objectCounterRectForTabCell:cell].size.width + kPSMTabBarCellPadding);
// label
[[cell attributedStringValue] drawInRect:labelRect];
}
- (void)drawTabBar:(PSMTabBarControl *)bar inRect:(NSRect)rect
{
NSRect gradientRect = rect;
gradientRect.size.height -= 1.0;
NSBezierPath *path = [NSBezierPath bezierPathWithRect:gradientRect];
[path linearGradientFillWithStartColor:[NSColor colorWithCalibratedWhite:0.918 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)];
// 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];
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(![cell isInOverflowMenu]){
[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:_addTabButtonImage forKey:@"addTabButtonImage"];
[aCoder encodeObject:_addTabButtonPressedImage forKey:@"addTabButtonPressedImage"];
[aCoder encodeObject:_addTabButtonRolloverImage forKey:@"addTabButtonRolloverImage"];
}
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
// self = [super initWithCoder:aDecoder];
//if (self) {
if ([aDecoder allowsKeyedCoding]) {
unifiedCloseButton = [[aDecoder decodeObjectForKey:@"unifiedCloseButton"] retain];
unifiedCloseButtonDown = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonDown"] retain];
unifiedCloseButtonOver = [[aDecoder decodeObjectForKey:@"unifiedCloseButtonOver"] retain];
_addTabButtonImage = [[aDecoder decodeObjectForKey:@"addTabButtonImage"] retain];
_addTabButtonPressedImage = [[aDecoder decodeObjectForKey:@"addTabButtonPressedImage"] retain];
_addTabButtonRolloverImage = [[aDecoder decodeObjectForKey:@"addTabButtonRolloverImage"] retain];
}
//}
return self;
}
@end
Jump to Line
Something went wrong with that request. Please try again.