From 7b2694e9f6c35d9f50c3fb3cf38b0fc766478162 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Wed, 26 Jan 2011 10:52:13 +0000 Subject: Updated PSMTabBarControl source code to version from https://github.com/dergraf83/PSMTabBarControl svn path=/trunk/netsurf/; revision=11490 --- cocoa/PSMTabBarControl/Images/overflowImage.png | Bin 0 -> 256 bytes .../Images/overflowImagePressed.png | Bin 0 -> 250 bytes cocoa/PSMTabBarControl/Images/pi.png | Bin 0 -> 564 bytes cocoa/PSMTabBarControl/NSBezierPath_AMShading.h | 4 +- cocoa/PSMTabBarControl/NSBezierPath_AMShading.m | 86 +- cocoa/PSMTabBarControl/NSString_AITruncation.m | 14 +- cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h | 12 +- cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m | 127 +- cocoa/PSMTabBarControl/PSMProgressIndicator.h | 8 - cocoa/PSMTabBarControl/PSMProgressIndicator.m | 29 +- cocoa/PSMTabBarControl/PSMRolloverButton.h | 9 +- cocoa/PSMTabBarControl/PSMRolloverButton.m | 155 +- cocoa/PSMTabBarControl/PSMTabBarCell.h | 49 +- cocoa/PSMTabBarControl/PSMTabBarCell.m | 560 +++--- cocoa/PSMTabBarControl/PSMTabBarControl.h | 159 +- cocoa/PSMTabBarControl/PSMTabBarControl.m | 2126 ++++++++++---------- cocoa/PSMTabBarControl/PSMTabBarController.h | 17 +- cocoa/PSMTabBarControl/PSMTabBarController.m | 662 +++--- cocoa/PSMTabBarControl/PSMTabDragAssistant.h | 45 +- cocoa/PSMTabBarControl/PSMTabDragAssistant.m | 849 ++++---- cocoa/PSMTabBarControl/PSMTabDragView.h | 5 +- cocoa/PSMTabBarControl/PSMTabDragView.m | 26 +- cocoa/PSMTabBarControl/PSMTabDragWindow.h | 2 +- cocoa/PSMTabBarControl/PSMTabDragWindow.m | 23 +- .../PSMTabBarControl/PSMTabDragWindowController.h | 16 +- .../PSMTabBarControl/PSMTabDragWindowController.m | 66 +- cocoa/PSMTabBarControl/PSMTabStyle.h | 6 +- cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h | 31 +- cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m | 860 ++++---- 29 files changed, 2842 insertions(+), 3104 deletions(-) create mode 100644 cocoa/PSMTabBarControl/Images/overflowImage.png create mode 100644 cocoa/PSMTabBarControl/Images/overflowImagePressed.png create mode 100644 cocoa/PSMTabBarControl/Images/pi.png mode change 100755 => 100644 cocoa/PSMTabBarControl/NSBezierPath_AMShading.h mode change 100755 => 100644 cocoa/PSMTabBarControl/NSBezierPath_AMShading.m (limited to 'cocoa/PSMTabBarControl') diff --git a/cocoa/PSMTabBarControl/Images/overflowImage.png b/cocoa/PSMTabBarControl/Images/overflowImage.png new file mode 100644 index 000000000..2b762555d Binary files /dev/null and b/cocoa/PSMTabBarControl/Images/overflowImage.png differ diff --git a/cocoa/PSMTabBarControl/Images/overflowImagePressed.png b/cocoa/PSMTabBarControl/Images/overflowImagePressed.png new file mode 100644 index 000000000..b3918b344 Binary files /dev/null and b/cocoa/PSMTabBarControl/Images/overflowImagePressed.png differ diff --git a/cocoa/PSMTabBarControl/Images/pi.png b/cocoa/PSMTabBarControl/Images/pi.png new file mode 100644 index 000000000..4d598dc73 Binary files /dev/null and b/cocoa/PSMTabBarControl/Images/pi.png differ diff --git a/cocoa/PSMTabBarControl/NSBezierPath_AMShading.h b/cocoa/PSMTabBarControl/NSBezierPath_AMShading.h old mode 100755 new mode 100644 index aed6f13ba..fd2c2dde4 --- a/cocoa/PSMTabBarControl/NSBezierPath_AMShading.h +++ b/cocoa/PSMTabBarControl/NSBezierPath_AMShading.h @@ -12,8 +12,8 @@ @interface NSBezierPath (AMShading) -- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; -- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; +- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks) functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; +- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks) functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor; - (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor; - (void)linearVerticalGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor; diff --git a/cocoa/PSMTabBarControl/NSBezierPath_AMShading.m b/cocoa/PSMTabBarControl/NSBezierPath_AMShading.m old mode 100755 new mode 100644 index 73213f3b5..30ee24096 --- a/cocoa/PSMTabBarControl/NSBezierPath_AMShading.m +++ b/cocoa/PSMTabBarControl/NSBezierPath_AMShading.m @@ -11,8 +11,7 @@ @implementation NSBezierPath (AMShading) -static void linearShadedColor(void *info, const CGFloat *in, CGFloat *out) -{ +static void linearShadedColor(void *info, const CGFloat *in, CGFloat *out){ CGFloat *colors = (CGFloat *)info; *out++ = colors[0] + *in * colors[8]; *out++ = colors[1] + *in * colors[9]; @@ -20,12 +19,11 @@ static void linearShadedColor(void *info, const CGFloat *in, CGFloat *out) *out++ = colors[3] + *in * colors[11]; } -static void bilinearShadedColor(void *info, const CGFloat *in, CGFloat *out) -{ +static void bilinearShadedColor(void *info, const CGFloat *in, CGFloat *out){ CGFloat *colors = (CGFloat *)info; - CGFloat factor = (*in)*2.0; - if (*in > 0.5) { - factor = 2-factor; + CGFloat factor = (*in) * 2.0; + if(*in > 0.5) { + factor = 2 - factor; } *out++ = colors[0] + factor * colors[8]; *out++ = colors[1] + factor * colors[9]; @@ -33,95 +31,89 @@ static void bilinearShadedColor(void *info, const CGFloat *in, CGFloat *out) *out++ = colors[3] + factor * colors[11]; } -- (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor -{ +- (void)linearGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor { static const CGFunctionCallbacks callbacks = {0, &linearShadedColor, NULL}; - + [self customHorizontalFillWithCallbacks:callbacks firstColor:startColor secondColor:endColor]; } -- (void)linearVerticalGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor -{ +- (void)linearVerticalGradientFillWithStartColor:(NSColor *)startColor endColor:(NSColor *)endColor { static const CGFunctionCallbacks callbacks = {0, &linearShadedColor, NULL}; - + [self customVerticalFillWithCallbacks:callbacks firstColor:startColor secondColor:endColor]; } -- (void)bilinearGradientFillWithOuterColor:(NSColor *)outerColor innerColor:(NSColor *)innerColor -{ +- (void)bilinearGradientFillWithOuterColor:(NSColor *)outerColor innerColor:(NSColor *)innerColor { static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL}; [self customHorizontalFillWithCallbacks:callbacks firstColor:innerColor secondColor:outerColor]; } -- (void)customFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint -{ +- (void)customFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint { CGColorSpaceRef colorspace; CGShadingRef shading; CGFunctionRef function; - CGFloat colors[12]; // pointer to color values - + CGFloat colors[12]; // pointer to color values + // get my context CGContextRef currentContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; - + NSColor *deviceDependentFirstColor = [firstColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; NSColor *deviceDependentSecondColor = [secondColor colorUsingColorSpaceName:NSDeviceRGBColorSpace]; - + // set up colors for gradient colors[0] = [deviceDependentFirstColor redComponent]; colors[1] = [deviceDependentFirstColor greenComponent]; colors[2] = [deviceDependentFirstColor blueComponent]; colors[3] = [deviceDependentFirstColor alphaComponent]; - + colors[4] = [deviceDependentSecondColor redComponent]; colors[5] = [deviceDependentSecondColor greenComponent]; colors[6] = [deviceDependentSecondColor blueComponent]; colors[7] = [deviceDependentSecondColor alphaComponent]; - + // difference between start and end color for each color components - colors[8] = (colors[4]-colors[0]); - colors[9] = (colors[5]-colors[1]); - colors[10] = (colors[6]-colors[2]); - colors[11] = (colors[7]-colors[3]); - + colors[8] = (colors[4] - colors[0]); + colors[9] = (colors[5] - colors[1]); + colors[10] = (colors[6] - colors[2]); + colors[11] = (colors[7] - colors[3]); + // draw gradient colorspace = CGColorSpaceCreateDeviceRGB(); size_t components = 1 + CGColorSpaceGetNumberOfComponents(colorspace); - static const CGFloat domain[2] = {0.0, 1.0}; - static const CGFloat range[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; + static const CGFloat domain[2] = {0.0, 1.0}; + static const CGFloat range[10] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; //static const CGFunctionCallbacks callbacks = {0, &bilinearShadedColor, NULL}; - + // Create a CGFunctionRef that describes a function taking 1 input and kChannelsPerColor outputs. function = CGFunctionCreate(colors, 1, domain, components, range, &functionCallbacks); shading = CGShadingCreateAxial(colorspace, startPoint, endPoint, function, NO, NO); - + CGContextSaveGState(currentContext); [self addClip]; CGContextDrawShading(currentContext, shading); CGContextRestoreGState(currentContext); - + CGShadingRelease(shading); CGFunctionRelease(function); CGColorSpaceRelease(colorspace); } -- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor -{ - [self customFillWithCallbacks:functionCallbacks - firstColor:firstColor - secondColor:secondColor - startPoint:CGPointMake(0, NSMinY([self bounds])) - endPoint:CGPointMake(0, NSMaxY([self bounds]))]; +- (void)customHorizontalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor { + [self customFillWithCallbacks:functionCallbacks + firstColor:firstColor + secondColor:secondColor + startPoint:CGPointMake(0, NSMinY([self bounds])) + endPoint:CGPointMake(0, NSMaxY([self bounds]))]; } -- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor -{ - [self customFillWithCallbacks:functionCallbacks - firstColor:firstColor - secondColor:secondColor - startPoint:CGPointMake(NSMinX([self bounds]), 0) - endPoint:CGPointMake(NSMaxX([self bounds]), 0)]; +- (void)customVerticalFillWithCallbacks:(CGFunctionCallbacks)functionCallbacks firstColor:(NSColor *)firstColor secondColor:(NSColor *)secondColor { + [self customFillWithCallbacks:functionCallbacks + firstColor:firstColor + secondColor:secondColor + startPoint:CGPointMake(NSMinX([self bounds]), 0) + endPoint:CGPointMake(NSMaxX([self bounds]), 0)]; } @end diff --git a/cocoa/PSMTabBarControl/NSString_AITruncation.m b/cocoa/PSMTabBarControl/NSString_AITruncation.m index 567c78f2f..1a54502e5 100644 --- a/cocoa/PSMTabBarControl/NSString_AITruncation.m +++ b/cocoa/PSMTabBarControl/NSString_AITruncation.m @@ -11,23 +11,21 @@ @implementation NSString (AITruncation) -+ (id)ellipsis -{ ++ (id)ellipsis { return [NSString stringWithUTF8String:"\xE2\x80\xA6"]; } -- (NSString *)stringWithEllipsisByTruncatingToLength:(NSUInteger)length -{ +- (NSString *)stringWithEllipsisByTruncatingToLength:(NSUInteger)length { NSString *returnString; - - if (length < [self length]) { + + if(length < [self length]) { //Truncate and append the ellipsis - returnString = [[self substringToIndex:length-1] stringByAppendingString:[NSString ellipsis]]; + returnString = [[self substringToIndex:length - 1] stringByAppendingString:[NSString ellipsis]]; } else { //We don't need to truncate, so don't append an ellipsis returnString = [[self copy] autorelease]; } - + return returnString; } diff --git a/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h b/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h index 19ce95f11..decda5be4 100644 --- a/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h +++ b/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.h @@ -10,12 +10,12 @@ @interface PSMOverflowPopUpButton : NSPopUpButton { - NSImage *_PSMTabBarOverflowPopUpImage; - NSImage *_PSMTabBarOverflowDownPopUpImage; - BOOL _down; - BOOL _animatingAlternateImage; - NSTimer *_animationTimer; - CGFloat _animationValue; + NSImage *_PSMTabBarOverflowPopUpImage; + NSImage *_PSMTabBarOverflowDownPopUpImage; + BOOL _down; + BOOL _animatingAlternateImage; + NSTimer *_animationTimer; + CGFloat _animationValue; } //alternate image display diff --git a/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m b/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m index 4ac70451b..c316f6973 100644 --- a/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m +++ b/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m @@ -14,102 +14,94 @@ @implementation PSMOverflowPopUpButton -- (id)initWithFrame:(NSRect)frameRect pullsDown:(BOOL)flag -{ - if ((self = [super initWithFrame:frameRect pullsDown:YES]) != nil) { - [self setBezelStyle:NSRegularSquareBezelStyle]; - [self setBordered:NO]; - [self setTitle:@""]; - [self setPreferredEdge:NSMaxXEdge]; - _PSMTabBarOverflowPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImage"]]; +- (id)initWithFrame:(NSRect)frameRect pullsDown:(BOOL)flag { + if ((self = [super initWithFrame:frameRect pullsDown:YES]) != nil) { + [self setBezelStyle:NSRegularSquareBezelStyle]; + [self setBordered:NO]; + [self setTitle:@""]; + [self setPreferredEdge:NSMaxXEdge]; + _PSMTabBarOverflowPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImage"]]; _PSMTabBarOverflowDownPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImagePressed"]]; _animatingAlternateImage = NO; - } - return self; + } + return self; } -- (void)dealloc -{ - [_PSMTabBarOverflowPopUpImage release]; +- (void)dealloc { + [_PSMTabBarOverflowPopUpImage release]; [_PSMTabBarOverflowDownPopUpImage release]; - [super dealloc]; + [super dealloc]; } -- (void)drawRect:(NSRect)rect -{ - if(_PSMTabBarOverflowPopUpImage == nil){ - [super drawRect:rect]; - return; - } - - NSImage *image = (_down) ? _PSMTabBarOverflowDownPopUpImage : _PSMTabBarOverflowPopUpImage; +- (void)drawRect:(NSRect)rect { + if(_PSMTabBarOverflowPopUpImage == nil) { + [super drawRect:rect]; + return; + } + + NSImage *image = (_down) ? _PSMTabBarOverflowDownPopUpImage : _PSMTabBarOverflowPopUpImage; NSSize imageSize = [image size]; NSRect bounds = [self bounds]; - + NSPoint drawPoint = NSMakePoint(NSMidX(bounds) - (imageSize.width * 0.5f), NSMidY(bounds) - (imageSize.height * 0.5f)); - - if ([self isFlipped]) { - drawPoint.y += imageSize.height; - } - - [image compositeToPoint:drawPoint operation:NSCompositeSourceOver fraction:(_animatingAlternateImage ? 0.7f : 1.0f)]; - - if (_animatingAlternateImage) { + + if([self isFlipped]) { + drawPoint.y += imageSize.height; + } + + [image compositeToPoint:drawPoint operation:NSCompositeSourceOver fraction:(_animatingAlternateImage ? 0.7f : 1.0f)]; + + if(_animatingAlternateImage) { NSImage *alternateImage = [self alternateImage]; NSSize altImageSize = [alternateImage size]; drawPoint = NSMakePoint(NSMidX(bounds) - (altImageSize.width * 0.5f), NSMidY(bounds) - (altImageSize.height * 0.5f)); - - if ([self isFlipped]) { + + if([self isFlipped]) { drawPoint.y += altImageSize.height; } - + [[self alternateImage] compositeToPoint:drawPoint operation:NSCompositeSourceOver fraction:sin(_animationValue * M_PI)]; } } -- (void)mouseDown:(NSEvent *)event -{ +- (void)mouseDown:(NSEvent *)event { _down = YES; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationReceived:) name:NSMenuDidEndTrackingNotification object:[self menu]]; [self setNeedsDisplay:YES]; [super mouseDown:event]; } -- (void)setHidden:(BOOL)value -{ - if ([self isHidden] != value) { - if (value) { +- (void)setHidden:(BOOL)value { + if([self isHidden] != value) { + if(value) { // Stop any animating alternate image if we hide [_animationTimer invalidate], _animationTimer = nil; - } else if (_animatingAlternateImage) { + } else if(_animatingAlternateImage) { // Restart any animating alternate image if we unhide _animationValue = ANIMATION_STEP; _animationTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(animateStep:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; } } - + [super setHidden:value]; } -- (void)notificationReceived:(NSNotification *)notification -{ +- (void)notificationReceived:(NSNotification *)notification { _down = NO; [self setNeedsDisplay:YES]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (void)setAnimatingAlternateImage:(BOOL)flag -{ - if (_animatingAlternateImage != flag) { +- (void)setAnimatingAlternateImage:(BOOL)flag { + if(_animatingAlternateImage != flag) { _animatingAlternateImage = flag; - - if (![self isHidden]) { - if (flag) { + + if(![self isHidden]) { + if(flag) { _animationValue = ANIMATION_STEP; _animationTimer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(animateStep:) userInfo:nil repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; - } else { [_animationTimer invalidate], _animationTimer = nil; } @@ -124,14 +116,13 @@ return _animatingAlternateImage; } -- (void)animateStep:(NSTimer *)timer -{ +- (void)animateStep:(NSTimer *)timer { _animationValue += ANIMATION_STEP; - - if (_animationValue >= 1) { + + if(_animationValue >= 1) { _animationValue = ANIMATION_STEP; } - + [self setNeedsDisplay:YES]; } @@ -139,23 +130,23 @@ #pragma mark Archiving - (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_PSMTabBarOverflowPopUpImage forKey:@"PSMTabBarOverflowPopUpImage"]; - [aCoder encodeObject:_PSMTabBarOverflowDownPopUpImage forKey:@"PSMTabBarOverflowDownPopUpImage"]; + [super encodeWithCoder:aCoder]; + if([aCoder allowsKeyedCoding]) { + [aCoder encodeObject:_PSMTabBarOverflowPopUpImage forKey:@"PSMTabBarOverflowPopUpImage"]; + [aCoder encodeObject:_PSMTabBarOverflowDownPopUpImage forKey:@"PSMTabBarOverflowDownPopUpImage"]; [aCoder encodeBool:_animatingAlternateImage forKey:@"PSMTabBarOverflowAnimatingAlternateImage"]; - } + } } - (id)initWithCoder:(NSCoder *)aDecoder { - if ( (self = [super initWithCoder:aDecoder]) ) { - if ([aDecoder allowsKeyedCoding]) { - _PSMTabBarOverflowPopUpImage = [[aDecoder decodeObjectForKey:@"PSMTabBarOverflowPopUpImage"] retain]; - _PSMTabBarOverflowDownPopUpImage = [[aDecoder decodeObjectForKey:@"PSMTabBarOverflowDownPopUpImage"] retain]; + if((self = [super initWithCoder:aDecoder])) { + if([aDecoder allowsKeyedCoding]) { + _PSMTabBarOverflowPopUpImage = [[aDecoder decodeObjectForKey:@"PSMTabBarOverflowPopUpImage"] retain]; + _PSMTabBarOverflowDownPopUpImage = [[aDecoder decodeObjectForKey:@"PSMTabBarOverflowDownPopUpImage"] retain]; [self setAnimatingAlternateImage:[aDecoder decodeBoolForKey:@"PSMTabBarOverflowAnimatingAlternateImage"]]; - } - } - return self; + } + } + return self; } @end diff --git a/cocoa/PSMTabBarControl/PSMProgressIndicator.h b/cocoa/PSMTabBarControl/PSMProgressIndicator.h index 8f56bd73a..ffce06926 100644 --- a/cocoa/PSMTabBarControl/PSMProgressIndicator.h +++ b/cocoa/PSMTabBarControl/PSMProgressIndicator.h @@ -7,17 +7,9 @@ // #import -#import "PSMTabBarControl.h" @interface PSMProgressIndicator : NSProgressIndicator { - } -@end - -@interface PSMTabBarControl (LayoutPlease) - -- (void)update; - @end \ No newline at end of file diff --git a/cocoa/PSMTabBarControl/PSMProgressIndicator.m b/cocoa/PSMTabBarControl/PSMProgressIndicator.m index f79852a26..983609bbc 100644 --- a/cocoa/PSMTabBarControl/PSMProgressIndicator.m +++ b/cocoa/PSMTabBarControl/PSMProgressIndicator.m @@ -7,21 +7,34 @@ // #import "PSMProgressIndicator.h" +#import "PSMTabBarControl.h" + +@interface PSMTabBarControl (PSMProgressIndicatorExtensions) + +- (void)update; + +@end @implementation PSMProgressIndicator -// overrides to make tab bar control re-layout things if status changes -- (void)setHidden:(BOOL)flag +- (id) initWithFrame: (NSRect)frameRect; { - [super setHidden:flag]; - [(PSMTabBarControl *)[self superview] update]; + if ((self = [super initWithFrame: frameRect]) == nil) return nil; + [self setControlSize: NSSmallControlSize]; + return self; } -- (void)stopAnimation:(id)sender -{ +// overrides to make tab bar control re-layout things if status changes +- (void)setHidden:(BOOL)flag { + [super setHidden:flag]; + [(PSMTabBarControl *)[self superview] update]; +} + +- (void)stopAnimation:(id)sender { [NSObject cancelPreviousPerformRequestsWithTarget:self - selector:@selector(startAnimation:) - object:nil]; + selector:@selector(startAnimation:) + object:nil]; [super stopAnimation:sender]; } + @end diff --git a/cocoa/PSMTabBarControl/PSMRolloverButton.h b/cocoa/PSMTabBarControl/PSMRolloverButton.h index d78b47c27..62fce23e0 100644 --- a/cocoa/PSMTabBarControl/PSMRolloverButton.h +++ b/cocoa/PSMTabBarControl/PSMRolloverButton.h @@ -8,11 +8,10 @@ #import -@interface PSMRolloverButton : NSButton -{ - NSImage *_rolloverImage; - NSImage *_usualImage; - NSTrackingRectTag _myTrackingRectTag; +@interface PSMRolloverButton : NSButton { + NSImage *_rolloverImage; + NSImage *_usualImage; + NSTrackingRectTag _myTrackingRectTag; } // the regular image diff --git a/cocoa/PSMTabBarControl/PSMRolloverButton.m b/cocoa/PSMTabBarControl/PSMRolloverButton.m index 988abbb2a..e6f0816a2 100644 --- a/cocoa/PSMTabBarControl/PSMRolloverButton.m +++ b/cocoa/PSMTabBarControl/PSMRolloverButton.m @@ -10,110 +10,98 @@ @implementation PSMRolloverButton -- (void)awakeFromNib -{ - if ([[self superclass] instancesRespondToSelector:@selector(awakeFromNib)]) { - [super awakeFromNib]; +- (void)awakeFromNib { + if([[self superclass] instancesRespondToSelector:@selector(awakeFromNib)]) { + [super awakeFromNib]; } - - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(rolloverFrameDidChange:) - name:NSViewFrameDidChangeNotification - object:self]; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(rolloverFrameDidChange:) + name:NSViewFrameDidChangeNotification + object:self]; [self setPostsFrameChangedNotifications:YES]; [self resetCursorRects]; - + _myTrackingRectTag = -1; } -- (void)dealloc -{ +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - + [self removeTrackingRect]; - + [super dealloc]; } // the regular image -- (void)setUsualImage:(NSImage *)newImage -{ - [newImage retain]; - [_usualImage release]; - _usualImage = newImage; +- (void)setUsualImage:(NSImage *)newImage { + [newImage retain]; + [_usualImage release]; + _usualImage = newImage; [self setImage:_usualImage]; } -- (NSImage *)usualImage -{ - return _usualImage; +- (NSImage *)usualImage { + return _usualImage; } -- (void)setRolloverImage:(NSImage *)newImage -{ - [newImage retain]; - [_rolloverImage release]; - _rolloverImage = newImage; +- (void)setRolloverImage:(NSImage *)newImage { + [newImage retain]; + [_rolloverImage release]; + _rolloverImage = newImage; } -- (NSImage *)rolloverImage -{ - return _rolloverImage; +- (NSImage *)rolloverImage { + return _rolloverImage; } //Remove old tracking rects when we change superviews -- (void)viewWillMoveToSuperview:(NSView *)newSuperview -{ +- (void)viewWillMoveToSuperview:(NSView *)newSuperview { [self removeTrackingRect]; - + [super viewWillMoveToSuperview:newSuperview]; } -- (void)viewDidMoveToSuperview -{ +- (void)viewDidMoveToSuperview { [super viewDidMoveToSuperview]; - + [self resetCursorRects]; } -- (void)viewWillMoveToWindow:(NSWindow *)newWindow -{ +- (void)viewWillMoveToWindow:(NSWindow *)newWindow { [self removeTrackingRect]; - + [super viewWillMoveToWindow:newWindow]; } -- (void)viewDidMoveToWindow -{ +- (void)viewDidMoveToWindow { [super viewDidMoveToWindow]; - + [self resetCursorRects]; } -- (void)rolloverFrameDidChange:(NSNotification *)inNotification -{ +- (void)rolloverFrameDidChange:(NSNotification *)inNotification { [self resetCursorRects]; } -- (void)addTrackingRect -{ - // assign a tracking rect to watch for mouse enter/exit - NSRect trackRect = [self bounds]; - NSPoint localPoint = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] - fromView:nil]; - BOOL mouseInside = NSPointInRect(localPoint, trackRect); - - _myTrackingRectTag = [self addTrackingRect:trackRect owner:self userData:nil assumeInside:mouseInside]; - if (mouseInside) +- (void)addTrackingRect { + // assign a tracking rect to watch for mouse enter/exit + NSRect trackRect = [self bounds]; + NSPoint localPoint = [self convertPoint:[[self window] convertScreenToBase:[NSEvent mouseLocation]] + fromView:nil]; + BOOL mouseInside = NSPointInRect(localPoint, trackRect); + + _myTrackingRectTag = [self addTrackingRect:trackRect owner:self userData:nil assumeInside:mouseInside]; + if(mouseInside) { [self mouseEntered:nil]; - else + } else{ [self mouseExited:nil]; + } } -- (void)removeTrackingRect -{ - if (_myTrackingRectTag != -1) { +- (void)removeTrackingRect { + if(_myTrackingRectTag != -1) { [self removeTrackingRect:_myTrackingRectTag]; } _myTrackingRectTag = -1; @@ -122,35 +110,32 @@ // override for rollover effect - (void)mouseEntered:(NSEvent *)theEvent; { - // set rollover image - [self setImage:_rolloverImage]; + // set rollover image + [self setImage:_rolloverImage]; [super mouseEntered:theEvent]; } - (void)mouseExited:(NSEvent *)theEvent; { - // restore usual image + // restore usual image [self setImage:_usualImage]; [super mouseExited:theEvent]; } -- (void)resetCursorRects -{ - // called when the button rect has been changed - [self removeTrackingRect]; - [self addTrackingRect]; +- (void)resetCursorRects { + // called when the button rect has been changed + [self removeTrackingRect]; + [self addTrackingRect]; } -- (void)setFrame:(NSRect)rect -{ +- (void)setFrame:(NSRect)rect { [super setFrame:rect]; [self resetCursorRects]; } -- (void)setBounds:(NSRect)rect -{ +- (void)setBounds:(NSRect)rect { [super setBounds:rect]; [self resetCursorRects]; } @@ -159,24 +144,24 @@ #pragma mark Archiving - (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_rolloverImage forKey:@"rolloverImage"]; - [aCoder encodeObject:_usualImage forKey:@"usualImage"]; - [aCoder encodeInteger:_myTrackingRectTag forKey:@"myTrackingRectTag"]; - } + [super encodeWithCoder:aCoder]; + if([aCoder allowsKeyedCoding]) { + [aCoder encodeObject:_rolloverImage forKey:@"rolloverImage"]; + [aCoder encodeObject:_usualImage forKey:@"usualImage"]; + [aCoder encodeInt64:_myTrackingRectTag forKey:@"myTrackingRectTag"]; + } } - (id)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if (self) { - if ([aDecoder allowsKeyedCoding]) { - _rolloverImage = [[aDecoder decodeObjectForKey:@"rolloverImage"] retain]; - _usualImage = [[aDecoder decodeObjectForKey:@"usualImage"] retain]; - _myTrackingRectTag = [aDecoder decodeIntegerForKey:@"myTrackingRectTag"]; - } - } - return self; + self = [super initWithCoder:aDecoder]; + if(self) { + if([aDecoder allowsKeyedCoding]) { + _rolloverImage = [[aDecoder decodeObjectForKey:@"rolloverImage"] retain]; + _usualImage = [[aDecoder decodeObjectForKey:@"usualImage"] retain]; + _myTrackingRectTag = [aDecoder decodeInt64ForKey:@"myTrackingRectTag"]; + } + } + return self; } diff --git a/cocoa/PSMTabBarControl/PSMTabBarCell.h b/cocoa/PSMTabBarControl/PSMTabBarCell.h index 519c7ac47..c8f6cecdd 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarCell.h +++ b/cocoa/PSMTabBarControl/PSMTabBarCell.h @@ -8,37 +8,36 @@ #import #import "PSMTabBarControl.h" +#import "PSMProgressIndicator.h" -@class PSMTabBarControl; -@class PSMProgressIndicator; @interface PSMTabBarCell : NSActionCell { - // sizing - NSRect _frame; - NSSize _stringSize; - NSInteger _currentStep; - BOOL _isPlaceholder; - - // state - NSInteger _tabState; - NSTrackingRectTag _closeButtonTrackingTag; // left side tracking, if dragging - NSTrackingRectTag _cellTrackingTag; // right side tracking, if dragging - BOOL _closeButtonOver; - BOOL _closeButtonPressed; - PSMProgressIndicator *_indicator; - BOOL _isInOverflowMenu; - BOOL _hasCloseButton; - BOOL _isCloseButtonSuppressed; - BOOL _hasIcon; - BOOL _hasLargeImage; - NSInteger _count; - NSColor *_countColor; - BOOL _isEdited; + // sizing + NSRect _frame; + NSSize _stringSize; + NSInteger _currentStep; + BOOL _isPlaceholder; + + // state + NSInteger _tabState; + NSTrackingRectTag _closeButtonTrackingTag; // left side tracking, if dragging + NSTrackingRectTag _cellTrackingTag; // right side tracking, if dragging + BOOL _closeButtonOver; + BOOL _closeButtonPressed; + PSMProgressIndicator *_indicator; + BOOL _isInOverflowMenu; + BOOL _hasCloseButton; + BOOL _isCloseButtonSuppressed; + BOOL _hasIcon; + BOOL _hasLargeImage; + NSInteger _count; + NSColor *_countColor; + BOOL _isEdited; } // creation/destruction - (id)initWithControlView:(PSMTabBarControl *)controlView; -- (id)initPlaceholderWithFrame:(NSRect)frame expanded:(BOOL)value inControlView:(PSMTabBarControl *)controlView; +- (id)initPlaceholderWithFrame:(NSRect) frame expanded:(BOOL) value inControlView:(PSMTabBarControl *)controlView; - (void)dealloc; // accessors @@ -89,7 +88,7 @@ - (CGFloat)desiredWidthOfCell; // drawing -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView; +- (void)drawWithFrame:(NSRect) cellFrame inView:(NSView *)controlView; // tracking the mouse - (void)mouseEntered:(NSEvent *)theEvent; diff --git a/cocoa/PSMTabBarControl/PSMTabBarCell.m b/cocoa/PSMTabBarControl/PSMTabBarCell.m index d35f68ee5..f7a04f202 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarCell.m +++ b/cocoa/PSMTabBarControl/PSMTabBarCell.m @@ -20,375 +20,332 @@ #pragma mark - #pragma mark Creation/Destruction -- (id)initWithControlView:(PSMTabBarControl *)controlView -{ - if ( (self = [super init]) ) { - _controlView = controlView; - _closeButtonTrackingTag = 0; - _cellTrackingTag = 0; - _closeButtonOver = NO; - _closeButtonPressed = NO; - _indicator = [[PSMProgressIndicator alloc] initWithFrame:NSMakeRect(0.0,0.0,kPSMTabBarIndicatorWidth,kPSMTabBarIndicatorWidth)]; - [_indicator setStyle:NSProgressIndicatorSpinningStyle]; - [_indicator setAutoresizingMask:NSViewMinYMargin]; - _hasCloseButton = YES; - _isCloseButtonSuppressed = NO; - _count = 0; +- (id)initWithControlView:(PSMTabBarControl *)controlView { + if((self = [super init])) { + _controlView = controlView; + _closeButtonTrackingTag = 0; + _cellTrackingTag = 0; + _closeButtonOver = NO; + _closeButtonPressed = NO; + _indicator = [[PSMProgressIndicator alloc] initWithFrame:NSMakeRect(0.0, 0.0, kPSMTabBarIndicatorWidth, kPSMTabBarIndicatorWidth)]; + [_indicator setStyle:NSProgressIndicatorSpinningStyle]; + [_indicator setAutoresizingMask:NSViewMinYMargin]; + _hasCloseButton = YES; + _isCloseButtonSuppressed = NO; + _count = 0; _countColor = nil; - _isEdited = NO; - _isPlaceholder = NO; - } - return self; + _isEdited = NO; + _isPlaceholder = NO; + } + return self; } -- (id)initPlaceholderWithFrame:(NSRect)frame expanded:(BOOL)value inControlView:(PSMTabBarControl *)controlView -{ - if ( (self = [super init]) ) { - _controlView = controlView; - _isPlaceholder = YES; - if (!value) { - if ([controlView orientation] == PSMTabBarHorizontalOrientation) { +- (id)initPlaceholderWithFrame:(NSRect)frame expanded:(BOOL)value inControlView:(PSMTabBarControl *)controlView { + if((self = [super init])) { + _controlView = controlView; + _isPlaceholder = YES; + if(!value) { + if([controlView orientation] == PSMTabBarHorizontalOrientation) { frame.size.width = 0.0; } else { frame.size.height = 0.0; } } - [self setFrame:frame]; - _closeButtonTrackingTag = 0; - _cellTrackingTag = 0; - _closeButtonOver = NO; - _closeButtonPressed = NO; - _indicator = nil; - _hasCloseButton = YES; - _isCloseButtonSuppressed = NO; - _count = 0; + [self setFrame:frame]; + _closeButtonTrackingTag = 0; + _cellTrackingTag = 0; + _closeButtonOver = NO; + _closeButtonPressed = NO; + _indicator = nil; + _hasCloseButton = YES; + _isCloseButtonSuppressed = NO; + _count = 0; _countColor = nil; - _isEdited = NO; - - if (value) { - [self setCurrentStep:(kPSMTabDragAnimationSteps - 1)]; - } else { - [self setCurrentStep:0]; - } - } - return self; -} - -- (void)dealloc -{ + _isEdited = NO; + + if(value) { + [self setCurrentStep:(kPSMTabDragAnimationSteps - 1)]; + } else { + [self setCurrentStep:0]; + } + } + return self; +} + +- (void)dealloc { [_countColor release]; - + [_indicator removeFromSuperviewWithoutNeedingDisplay]; - [_indicator release]; - [super dealloc]; + [_indicator release]; + [super dealloc]; } #pragma mark - #pragma mark Accessors -- (id)controlView -{ - return _controlView; +- (id)controlView { + return _controlView; } -- (void)setControlView:(id)view -{ - // no retain release pattern, as this simply switches a tab to another view. - _controlView = view; +- (void)setControlView:(id)view { + // no retain release pattern, as this simply switches a tab to another view. + _controlView = view; } -- (NSTrackingRectTag)closeButtonTrackingTag -{ - return _closeButtonTrackingTag; +- (NSTrackingRectTag)closeButtonTrackingTag { + return _closeButtonTrackingTag; } -- (void)setCloseButtonTrackingTag:(NSTrackingRectTag)tag -{ - _closeButtonTrackingTag = tag; +- (void)setCloseButtonTrackingTag:(NSTrackingRectTag)tag { + _closeButtonTrackingTag = tag; } -- (NSTrackingRectTag)cellTrackingTag -{ - return _cellTrackingTag; +- (NSTrackingRectTag)cellTrackingTag { + return _cellTrackingTag; } -- (void)setCellTrackingTag:(NSTrackingRectTag)tag -{ - _cellTrackingTag = tag; +- (void)setCellTrackingTag:(NSTrackingRectTag)tag { + _cellTrackingTag = tag; } -- (CGFloat)width -{ - return _frame.size.width; +- (CGFloat)width { + return _frame.size.width; } -- (NSRect)frame -{ - return _frame; +- (NSRect)frame { + return _frame; } -- (void)setFrame:(NSRect)rect -{ - _frame = rect; - +- (void)setFrame:(NSRect)rect { + _frame = rect; + //move the status indicator along with the rest of the cell - if (![[self indicator] isHidden] && ![_controlView isTabBarHidden]) { + if(![[self indicator] isHidden] && ![_controlView isTabBarHidden]) { [[self indicator] setFrame:[self indicatorRectForFrame:rect]]; } } -- (void)setStringValue:(NSString *)aString -{ - [super setStringValue:aString]; - _stringSize = [[self attributedStringValue] size]; - // need to redisplay now - binding observation was too quick. - [_controlView update]; +- (void)setStringValue:(NSString *)aString { + [super setStringValue:aString]; + _stringSize = [[self attributedStringValue] size]; + // need to redisplay now - binding observation was too quick. + [_controlView update]; } -- (NSSize)stringSize -{ - return _stringSize; +- (NSSize)stringSize { + return _stringSize; } -- (NSAttributedString *)attributedStringValue -{ - return [(id )[_controlView style] attributedStringValueForTabCell:self]; +- (NSAttributedString *)attributedStringValue { + return [(id < PSMTabStyle >)[_controlView style] attributedStringValueForTabCell:self]; } -- (NSInteger)tabState -{ - return _tabState; +- (NSInteger)tabState { + return _tabState; } -- (void)setTabState:(NSInteger)state -{ - _tabState = state; +- (void)setTabState:(NSInteger)state { + _tabState = state; } -- (NSProgressIndicator *)indicator -{ - return _indicator; +- (NSProgressIndicator *)indicator { + return _indicator; } -- (BOOL)isInOverflowMenu -{ - return _isInOverflowMenu; +- (BOOL)isInOverflowMenu { + return _isInOverflowMenu; } -- (void)setIsInOverflowMenu:(BOOL)value -{ - if (_isInOverflowMenu != value) { +- (void)setIsInOverflowMenu:(BOOL)value { + if(_isInOverflowMenu != value) { _isInOverflowMenu = value; - if ([[[self controlView] delegate] respondsToSelector:@selector(tabView:tabViewItem:isInOverflowMenu:)]) { + if([[[self controlView] delegate] respondsToSelector:@selector(tabView:tabViewItem:isInOverflowMenu:)]) { [[[self controlView] delegate] tabView:[self controlView] tabViewItem:[self representedObject] isInOverflowMenu:_isInOverflowMenu]; } } } -- (BOOL)closeButtonPressed -{ - return _closeButtonPressed; +- (BOOL)closeButtonPressed { + return _closeButtonPressed; } -- (void)setCloseButtonPressed:(BOOL)value -{ - _closeButtonPressed = value; +- (void)setCloseButtonPressed:(BOOL)value { + _closeButtonPressed = value; } -- (BOOL)closeButtonOver -{ - return (_closeButtonOver && ([_controlView allowsBackgroundTabClosing] || ([self tabState] & PSMTab_SelectedMask) || [[NSApp currentEvent] modifierFlags] & NSCommandKeyMask)); +- (BOOL)closeButtonOver { + return(_closeButtonOver && ([_controlView allowsBackgroundTabClosing] || ([self tabState] & PSMTab_SelectedMask) || [[NSApp currentEvent] modifierFlags] & NSCommandKeyMask)); } -- (void)setCloseButtonOver:(BOOL)value -{ - _closeButtonOver = value; +- (void)setCloseButtonOver:(BOOL)value { + _closeButtonOver = value; } -- (BOOL)hasCloseButton -{ - return _hasCloseButton; +- (BOOL)hasCloseButton { + return _hasCloseButton; } - (void)setHasCloseButton:(BOOL)set; { - _hasCloseButton = set; + _hasCloseButton = set; } - (void)setCloseButtonSuppressed:(BOOL)suppress; { - _isCloseButtonSuppressed = suppress; + _isCloseButtonSuppressed = suppress; } - (BOOL)isCloseButtonSuppressed; { - return _isCloseButtonSuppressed; + return _isCloseButtonSuppressed; } -- (BOOL)hasIcon -{ - return _hasIcon; +- (BOOL)hasIcon { + return _hasIcon; } -- (void)setHasIcon:(BOOL)value -{ - _hasIcon = value; - //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast +- (void)setHasIcon:(BOOL)value { + _hasIcon = value; + //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast } -- (BOOL)hasLargeImage -{ +- (BOOL)hasLargeImage { return _hasLargeImage; } -- (void)setHasLargeImage:(BOOL)value -{ +- (void)setHasLargeImage:(BOOL)value { _hasLargeImage = value; } -- (NSInteger)count -{ - return _count; +- (NSInteger)count { + return _count; } -- (void)setCount:(NSInteger)value -{ - _count = value; - //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast +- (void)setCount:(NSInteger)value { + _count = value; + //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast } -- (NSColor *)countColor -{ +- (NSColor *)countColor { return _countColor; } -- (void)setCountColor:(NSColor *)color -{ +- (void)setCountColor:(NSColor *)color { [_countColor release]; _countColor = [color retain]; } -- (BOOL)isPlaceholder -{ - return _isPlaceholder; +- (BOOL)isPlaceholder { + return _isPlaceholder; } - (void)setIsPlaceholder:(BOOL)value; { - _isPlaceholder = value; + _isPlaceholder = value; } -- (NSInteger)currentStep -{ - return _currentStep; +- (NSInteger)currentStep { + return _currentStep; } -- (void)setCurrentStep:(NSInteger)value -{ - if(value < 0) - value = 0; - - if(value > (kPSMTabDragAnimationSteps - 1)) - value = (kPSMTabDragAnimationSteps - 1); - - _currentStep = value; +- (void)setCurrentStep:(NSInteger)value { + if(value < 0) { + value = 0; + } + + if(value > (kPSMTabDragAnimationSteps - 1)) { + value = (kPSMTabDragAnimationSteps - 1); + } + + _currentStep = value; } -- (BOOL)isEdited -{ - return _isEdited; +- (BOOL)isEdited { + return _isEdited; } -- (void)setIsEdited:(BOOL)value -{ - _isEdited = value; - //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast +- (void)setIsEdited:(BOOL)value { + _isEdited = value; + //[_controlView update:[[self controlView] automaticallyAnimates]]; // binding notice is too fast } #pragma mark - #pragma mark Bindings -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - // the progress indicator, label, icon, or count has changed - redraw the control view - //[_controlView update]; - //I seem to have run into some odd issue with update not being called at the right time. This seems to avoid the problem. - [_controlView performSelector:@selector(update) withObject:nil afterDelay:0.0]; +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + // the progress indicator, label, icon, or count has changed - redraw the control view + //[_controlView update]; + //I seem to have run into some odd issue with update not being called at the right time. This seems to avoid the problem. + [_controlView performSelector:@selector(update) withObject:nil afterDelay:0.0]; } #pragma mark - #pragma mark Component Attributes -- (NSRect)indicatorRectForFrame:(NSRect)cellFrame -{ - return [(id )[_controlView style] indicatorRectForTabCell:self]; +- (NSRect)indicatorRectForFrame:(NSRect)cellFrame { + return [(id < PSMTabStyle >)[_controlView style] indicatorRectForTabCell:self]; } -- (NSRect)closeButtonRectForFrame:(NSRect)cellFrame -{ - return [(id )[_controlView style] closeButtonRectForTabCell:self withFrame:cellFrame]; +- (NSRect)closeButtonRectForFrame:(NSRect)cellFrame { + return [(id < PSMTabStyle >)[_controlView style] closeButtonRectForTabCell:self withFrame:cellFrame]; } -- (CGFloat)minimumWidthOfCell -{ - return [(id )[_controlView style] minimumWidthOfTabCell:self]; +- (CGFloat)minimumWidthOfCell { + return [(id < PSMTabStyle >)[_controlView style] minimumWidthOfTabCell:self]; } -- (CGFloat)desiredWidthOfCell -{ - return [(id )[_controlView style] desiredWidthOfTabCell:self]; -} +- (CGFloat)desiredWidthOfCell { + return [(id < PSMTabStyle >)[_controlView style] desiredWidthOfTabCell:self]; +} #pragma mark - #pragma mark Drawing -- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView -{ - if (_isPlaceholder) { - [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; - NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); - return; - } - - [(id )[_controlView style] drawTabCell:self]; +- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView { + if(_isPlaceholder) { + [[NSColor colorWithCalibratedWhite:0.0 alpha:0.2] set]; + NSRectFillUsingOperation(cellFrame, NSCompositeSourceAtop); + return; + } + + [(id < PSMTabStyle >)[_controlView style] drawTabCell:self]; } #pragma mark - #pragma mark Tracking -- (void)mouseEntered:(NSEvent *)theEvent -{ - // check for which tag - if ([theEvent trackingNumber] == _closeButtonTrackingTag) { - _closeButtonOver = YES; - } - if ([theEvent trackingNumber] == _cellTrackingTag) { - [self setHighlighted:YES]; +- (void)mouseEntered:(NSEvent *)theEvent { + // check for which tag + if([theEvent trackingNumber] == _closeButtonTrackingTag) { + _closeButtonOver = YES; + } + if([theEvent trackingNumber] == _cellTrackingTag) { + [self setHighlighted:YES]; [_controlView setNeedsDisplay:NO]; - } - + } + // scrubtastic - if ([_controlView allowsScrubbing] && ([theEvent modifierFlags] & NSAlternateKeyMask)) + if([_controlView allowsScrubbing] && ([theEvent modifierFlags] & NSAlternateKeyMask)) { [_controlView performSelector:@selector(tabClick:) withObject:self]; - + } + // tell the control we only need to redraw the affected tab [_controlView setNeedsDisplayInRect:NSInsetRect([self frame], -2, -2)]; } -- (void)mouseExited:(NSEvent *)theEvent -{ - // check for which tag - if ([theEvent trackingNumber] == _closeButtonTrackingTag) { - _closeButtonOver = NO; - } - - if ([theEvent trackingNumber] == _cellTrackingTag) { - [self setHighlighted:NO]; +- (void)mouseExited:(NSEvent *)theEvent { + // check for which tag + if([theEvent trackingNumber] == _closeButtonTrackingTag) { + _closeButtonOver = NO; + } + + if([theEvent trackingNumber] == _cellTrackingTag) { + [self setHighlighted:NO]; [_controlView setNeedsDisplay:NO]; - } - + } + //tell the control we only need to redraw the affected tab [_controlView setNeedsDisplayInRect:NSInsetRect([self frame], -2, -2)]; } @@ -396,81 +353,80 @@ #pragma mark - #pragma mark Drag Support -- (NSImage *)dragImage -{ - NSRect cellFrame = [(id )[(PSMTabBarControl *)_controlView style] dragRectForTabCell:self orientation:(PSMTabBarOrientation)[(PSMTabBarControl *)_controlView orientation]]; +- (NSImage *)dragImage { + NSRect cellFrame = [(id < PSMTabStyle >)[(PSMTabBarControl *)_controlView style] dragRectForTabCell:self orientation:(PSMTabBarOrientation)[(PSMTabBarControl *)_controlView orientation]]; //NSRect cellFrame = [self frame]; - - [_controlView lockFocus]; - NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:cellFrame] autorelease]; - [_controlView unlockFocus]; - NSImage *image = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; - [image addRepresentation:rep]; - NSImage *returnImage = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; - [returnImage lockFocus]; - [image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeSourceOver fraction:1.0]; - [returnImage unlockFocus]; - if (![[self indicator] isHidden]) { - NSImage *pi = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"pi"]]; - [returnImage lockFocus]; - NSPoint indicatorPoint = NSMakePoint([self frame].size.width - MARGIN_X - kPSMTabBarIndicatorWidth, MARGIN_Y); - [pi compositeToPoint:indicatorPoint operation:NSCompositeSourceOver fraction:1.0]; - [returnImage unlockFocus]; - [pi release]; - } - return returnImage; + + [_controlView lockFocus]; + NSBitmapImageRep *rep = [[[NSBitmapImageRep alloc] initWithFocusedViewRect:cellFrame] autorelease]; + [_controlView unlockFocus]; + NSImage *image = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; + [image addRepresentation:rep]; + NSImage *returnImage = [[[NSImage alloc] initWithSize:[rep size]] autorelease]; + [returnImage lockFocus]; + [image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeSourceOver fraction:1.0]; + [returnImage unlockFocus]; + if(![[self indicator] isHidden]) { + NSImage *pi = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"pi"]]; + [returnImage lockFocus]; + NSPoint indicatorPoint = NSMakePoint([self frame].size.width - MARGIN_X - kPSMTabBarIndicatorWidth, MARGIN_Y); + [pi compositeToPoint:indicatorPoint operation:NSCompositeSourceOver fraction:1.0]; + [returnImage unlockFocus]; + [pi release]; + } + return returnImage; } #pragma mark - #pragma mark Archiving - (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeRect:_frame forKey:@"frame"]; - [aCoder encodeSize:_stringSize forKey:@"stringSize"]; - [aCoder encodeInteger:_currentStep forKey:@"currentStep"]; - [aCoder encodeBool:_isPlaceholder forKey:@"isPlaceholder"]; - [aCoder encodeInteger:_tabState forKey:@"tabState"]; - [aCoder encodeInteger:_closeButtonTrackingTag forKey:@"closeButtonTrackingTag"]; - [aCoder encodeInteger:_cellTrackingTag forKey:@"cellTrackingTag"]; - [aCoder encodeBool:_closeButtonOver forKey:@"closeButtonOver"]; - [aCoder encodeBool:_closeButtonPressed forKey:@"closeButtonPressed"]; - [aCoder encodeObject:_indicator forKey:@"indicator"]; - [aCoder encodeBool:_isInOverflowMenu forKey:@"isInOverflowMenu"]; - [aCoder encodeBool:_hasCloseButton forKey:@"hasCloseButton"]; - [aCoder encodeBool:_isCloseButtonSuppressed forKey:@"isCloseButtonSuppressed"]; - [aCoder encodeBool:_hasIcon forKey:@"hasIcon"]; - [aCoder encodeBool:_hasLargeImage forKey:@"hasLargeImage"]; - [aCoder encodeInteger:_count forKey:@"count"]; - [aCoder encodeBool:_isEdited forKey:@"isEdited"]; - } + [super encodeWithCoder:aCoder]; + if([aCoder allowsKeyedCoding]) { + [aCoder encodeRect:_frame forKey:@"frame"]; + [aCoder encodeSize:_stringSize forKey:@"stringSize"]; + [aCoder encodeInteger:_currentStep forKey:@"currentStep"]; + [aCoder encodeBool:_isPlaceholder forKey:@"isPlaceholder"]; + [aCoder encodeInteger:_tabState forKey:@"tabState"]; + [aCoder encodeInteger:_closeButtonTrackingTag forKey:@"closeButtonTrackingTag"]; + [aCoder encodeInteger:_cellTrackingTag forKey:@"cellTrackingTag"]; + [aCoder encodeBool:_closeButtonOver forKey:@"closeButtonOver"]; + [aCoder encodeBool:_closeButtonPressed forKey:@"closeButtonPressed"]; + [aCoder encodeObject:_indicator forKey:@"indicator"]; + [aCoder encodeBool:_isInOverflowMenu forKey:@"isInOverflowMenu"]; + [aCoder encodeBool:_hasCloseButton forKey:@"hasCloseButton"]; + [aCoder encodeBool:_isCloseButtonSuppressed forKey:@"isCloseButtonSuppressed"]; + [aCoder encodeBool:_hasIcon forKey:@"hasIcon"]; + [aCoder encodeBool:_hasLargeImage forKey:@"hasLargeImage"]; + [aCoder encodeInteger:_count forKey:@"count"]; + [aCoder encodeBool:_isEdited forKey:@"isEdited"]; + } } - (id)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if (self) { - if ([aDecoder allowsKeyedCoding]) { - _frame = [aDecoder decodeRectForKey:@"frame"]; - _stringSize = [aDecoder decodeSizeForKey:@"stringSize"]; - _currentStep = [aDecoder decodeIntegerForKey:@"currentStep"]; - _isPlaceholder = [aDecoder decodeBoolForKey:@"isPlaceholder"]; - _tabState = [aDecoder decodeIntegerForKey:@"tabState"]; - _closeButtonTrackingTag = [aDecoder decodeIntegerForKey:@"closeButtonTrackingTag"]; - _cellTrackingTag = [aDecoder decodeIntegerForKey:@"cellTrackingTag"]; - _closeButtonOver = [aDecoder decodeBoolForKey:@"closeButtonOver"]; - _closeButtonPressed = [aDecoder decodeBoolForKey:@"closeButtonPressed"]; - _indicator = [[aDecoder decodeObjectForKey:@"indicator"] retain]; - _isInOverflowMenu = [aDecoder decodeBoolForKey:@"isInOverflowMenu"]; - _hasCloseButton = [aDecoder decodeBoolForKey:@"hasCloseButton"]; - _isCloseButtonSuppressed = [aDecoder decodeBoolForKey:@"isCloseButtonSuppressed"]; - _hasIcon = [aDecoder decodeBoolForKey:@"hasIcon"]; - _hasLargeImage = [aDecoder decodeBoolForKey:@"hasLargeImage"]; - _count = [aDecoder decodeIntegerForKey:@"count"]; - _isEdited = [aDecoder decodeBoolForKey:@"isEdited"]; - } - } - return self; + self = [super initWithCoder:aDecoder]; + if(self) { + if([aDecoder allowsKeyedCoding]) { + _frame = [aDecoder decodeRectForKey:@"frame"]; + _stringSize = [aDecoder decodeSizeForKey:@"stringSize"]; + _currentStep = [aDecoder decodeIntegerForKey:@"currentStep"]; + _isPlaceholder = [aDecoder decodeBoolForKey:@"isPlaceholder"]; + _tabState = [aDecoder decodeIntegerForKey:@"tabState"]; + _closeButtonTrackingTag = [aDecoder decodeIntegerForKey:@"closeButtonTrackingTag"]; + _cellTrackingTag = [aDecoder decodeIntegerForKey:@"cellTrackingTag"]; + _closeButtonOver = [aDecoder decodeBoolForKey:@"closeButtonOver"]; + _closeButtonPressed = [aDecoder decodeBoolForKey:@"closeButtonPressed"]; + _indicator = [[aDecoder decodeObjectForKey:@"indicator"] retain]; + _isInOverflowMenu = [aDecoder decodeBoolForKey:@"isInOverflowMenu"]; + _hasCloseButton = [aDecoder decodeBoolForKey:@"hasCloseButton"]; + _isCloseButtonSuppressed = [aDecoder decodeBoolForKey:@"isCloseButtonSuppressed"]; + _hasIcon = [aDecoder decodeBoolForKey:@"hasIcon"]; + _hasLargeImage = [aDecoder decodeBoolForKey:@"hasLargeImage"]; + _count = [aDecoder decodeIntegerForKey:@"count"]; + _isEdited = [aDecoder decodeBoolForKey:@"isEdited"]; + } + } + return self; } #pragma mark - @@ -483,42 +439,40 @@ - (id)accessibilityAttributeValue:(NSString *)attribute { id attributeValue = nil; - if ([attribute isEqualToString: NSAccessibilityRoleAttribute]) { + if([attribute isEqualToString: NSAccessibilityRoleAttribute]) { attributeValue = NSAccessibilityButtonRole; - } else if ([attribute isEqualToString: NSAccessibilityHelpAttribute]) { - if ([[[self controlView] delegate] respondsToSelector:@selector(accessibilityStringForTabView:objectCount:)]) { + } else if([attribute isEqualToString: NSAccessibilityHelpAttribute]) { + if([[[self controlView] delegate] respondsToSelector:@selector(accessibilityStringForTabView:objectCount:)]) { attributeValue = [NSString stringWithFormat:@"%@, %lu %@", [self stringValue], - (unsigned long)[self count], - [[[self controlView] delegate] accessibilityStringForTabView:[[self controlView] tabView] objectCount:[self count]]]; + (unsigned long)[self count], + [[[self controlView] delegate] accessibilityStringForTabView:[[self controlView] tabView] objectCount:[self count]]]; } else { attributeValue = [self stringValue]; } - } else if ([attribute isEqualToString: NSAccessibilityFocusedAttribute]) { + } else if([attribute isEqualToString: NSAccessibilityFocusedAttribute]) { attributeValue = [NSNumber numberWithBool:([self tabState] == 2)]; } else { - attributeValue = [super accessibilityAttributeValue:attribute]; - } + attributeValue = [super accessibilityAttributeValue:attribute]; + } return attributeValue; } -- (NSArray *)accessibilityActionNames -{ +- (NSArray *)accessibilityActionNames { static NSArray *actions; - - if (!actions) { + + if(!actions) { actions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, nil]; } return actions; } -- (NSString *)accessibilityActionDescription:(NSString *)action -{ +- (NSString *)accessibilityActionDescription:(NSString *)action { return NSAccessibilityActionDescription(action); } - + - (void)accessibilityPerformAction:(NSString *)action { - if ([action isEqualToString:NSAccessibilityPressAction]) { + if([action isEqualToString:NSAccessibilityPressAction]) { // this tab was selected [_controlView performSelector:@selector(tabClick:) withObject:self]; } diff --git a/cocoa/PSMTabBarControl/PSMTabBarControl.h b/cocoa/PSMTabBarControl/PSMTabBarControl.h index c61b92f42..5ad02e5c1 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarControl.h +++ b/cocoa/PSMTabBarControl/PSMTabBarControl.h @@ -7,33 +7,36 @@ // /* - This view provides a control interface to manage a regular NSTabView. It looks and works like the tabbed browsing interface of many popular browsers. + This view provides a control interface to manage a regular NSTabView. It looks and works like the tabbed browsing interface of many popular browsers. */ #import -#define PSMTabDragDidEndNotification @"PSMTabDragDidEndNotification" -#define PSMTabDragDidBeginNotification @"PSMTabDragDidBeginNotification" +#define PSMTabDragDidEndNotification @ "PSMTabDragDidEndNotification" +#define PSMTabDragDidBeginNotification @ "PSMTabDragDidBeginNotification" -#define kPSMTabBarControlHeight 22 +#define kPSMTabBarControlHeight 22 // internal cell border -#define MARGIN_X 6 -#define MARGIN_Y 3 +#define MARGIN_X 6 +#define MARGIN_Y 3 // padding between objects -#define kPSMTabBarCellPadding 4 +#define kPSMTabBarCellPadding 4 // fixed size objects -#define kPSMMinimumTitleWidth 30 -#define kPSMTabBarIndicatorWidth 16.0 -#define kPSMTabBarIconWidth 16.0 -#define kPSMHideAnimationSteps 3.0 +#define kPSMMinimumTitleWidth 30 +#define kPSMTabBarIndicatorWidth 16.0 +#define kPSMTabBarIconWidth 16.0 +#define kPSMHideAnimationSteps 3.0 // Value used in _currentStep to indicate that resizing operation is not in progress -#define kPSMIsNotBeingResized -1 +#define kPSMIsNotBeingResized -1 // Value used in _currentStep when a resizing operation has just been started -#define kPSMStartResizeAnimation 0 +#define kPSMStartResizeAnimation 0 -@class PSMOverflowPopUpButton, PSMRolloverButton, PSMTabBarCell, PSMTabBarController; +@class PSMOverflowPopUpButton; +@class PSMRolloverButton; +@class PSMTabBarCell; +@class PSMTabBarController; @protocol PSMTabStyle; typedef enum { @@ -47,72 +50,72 @@ typedef enum { } PSMTabBarTearOffStyle; enum { - PSMTab_SelectedMask = 1 << 1, - PSMTab_LeftIsSelectedMask = 1 << 2, - PSMTab_RightIsSelectedMask = 1 << 3, - PSMTab_PositionLeftMask = 1 << 4, - PSMTab_PositionMiddleMask = 1 << 5, - PSMTab_PositionRightMask = 1 << 6, - PSMTab_PositionSingleMask = 1 << 7 + PSMTab_SelectedMask = 1 << 1, + PSMTab_LeftIsSelectedMask = 1 << 2, + PSMTab_RightIsSelectedMask = 1 << 3, + PSMTab_PositionLeftMask = 1 << 4, + PSMTab_PositionMiddleMask = 1 << 5, + PSMTab_PositionRightMask = 1 << 6, + PSMTab_PositionSingleMask = 1 << 7, }; @interface PSMTabBarControl : NSControl { - - // control basics - NSMutableArray *_cells; // the cells that draw the tabs - IBOutlet NSTabView *tabView; // the tab view being navigated - PSMOverflowPopUpButton *_overflowPopUpButton; // for too many tabs - PSMRolloverButton *_addTabButton; - PSMTabBarController *_controller; - - // Spring-loading. - NSTimer *_springTimer; - NSTabViewItem *_tabViewItemWithSpring; - - // drawing style - id style; - BOOL _canCloseOnlyTab; - BOOL _disableTabClose; - BOOL _hideForSingleTab; - BOOL _showAddTabButton; - BOOL _sizeCellsToFit; - BOOL _useOverflowMenu; - BOOL _alwaysShowActiveTab; - BOOL _allowsScrubbing; - NSInteger _resizeAreaCompensation; - PSMTabBarOrientation _orientation; - BOOL _automaticallyAnimates; - NSTimer *_animationTimer; - PSMTabBarTearOffStyle _tearOffStyle; - + + // control basics + NSMutableArray *_cells; // the cells that draw the tabs + IBOutlet NSTabView *tabView; // the tab view being navigated + PSMOverflowPopUpButton *_overflowPopUpButton; // for too many tabs + PSMRolloverButton *_addTabButton; + PSMTabBarController *_controller; + + // Spring-loading. + NSTimer *_springTimer; + NSTabViewItem *_tabViewItemWithSpring; + + // drawing style + id style; + BOOL _canCloseOnlyTab; + BOOL _disableTabClose; + BOOL _hideForSingleTab; + BOOL _showAddTabButton; + BOOL _sizeCellsToFit; + BOOL _useOverflowMenu; + BOOL _alwaysShowActiveTab; + BOOL _allowsScrubbing; + NSInteger _resizeAreaCompensation; + PSMTabBarOrientation _orientation; + BOOL _automaticallyAnimates; + NSTimer *_animationTimer; + PSMTabBarTearOffStyle _tearOffStyle; + // behavior - BOOL _allowsBackgroundTabClosing; - BOOL _selectsTabsOnMouseDown; - + BOOL _allowsBackgroundTabClosing; + BOOL _selectsTabsOnMouseDown; + // vertical tab resizing - BOOL _allowsResizing; - BOOL _resizing; - - // cell width - NSInteger _cellMinWidth; - NSInteger _cellMaxWidth; - NSInteger _cellOptimumWidth; - - // animation for hide/show - NSInteger _currentStep; - BOOL _isHidden; - IBOutlet id partnerView; // gets resized when hide/show - BOOL _awakenedFromNib; - NSInteger _tabBarWidth; - NSTimer *_showHideAnimationTimer; - - // drag and drop - NSEvent *_lastMouseDownEvent; // keep this for dragging reference - BOOL _didDrag; - BOOL _closeClicked; - - // MVC help - IBOutlet id delegate; + BOOL _allowsResizing; + BOOL _resizing; + + // cell width + NSInteger _cellMinWidth; + NSInteger _cellMaxWidth; + NSInteger _cellOptimumWidth; + + // animation for hide/show + NSInteger _currentStep; + BOOL _isHidden; + IBOutlet id partnerView; // gets resized when hide/show + BOOL _awakenedFromNib; + NSInteger _tabBarWidth; + NSTimer *_showHideAnimationTimer; + + // drag and drop + NSEvent *_lastMouseDownEvent; // keep this for dragging reference + BOOL _didDrag; + BOOL _closeClicked; + + // MVC help + IBOutlet id delegate; } // control characteristics @@ -160,6 +163,8 @@ enum { - (PSMTabBarTearOffStyle)tearOffStyle; - (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; ++ (Class) defaultStyleClass; + // accessors - (NSTabView *)tabView; - (void)setTabView:(NSTabView *)view; @@ -178,7 +183,7 @@ enum { - (PSMTabBarCell *)lastVisibleTab; // special effects -- (void)hideTabBar:(BOOL)hide animate:(BOOL)animate; +- (void)hideTabBar:(BOOL) hide animate:(BOOL)animate; - (BOOL)isTabBarHidden; - (BOOL)isAnimating; @@ -197,7 +202,7 @@ enum { //"Spring-loaded" tabs methods - (NSArray *)allowedDraggedTypesForTabView:(NSTabView *)aTabView; -- (void)tabView:(NSTabView *)aTabView acceptedDraggingInfo:(id )draggingInfo onTabViewItem:(NSTabViewItem *)tabViewItem; +- (void)tabView:(NSTabView *)aTabView acceptedDraggingInfo:(id ) draggingInfo onTabViewItem:(NSTabViewItem *)tabViewItem; //Contextual menu method - (NSMenu *)tabView:(NSTabView *)aTabView menuForTabViewItem:(NSTabViewItem *)tabViewItem; diff --git a/cocoa/PSMTabBarControl/PSMTabBarControl.m b/cocoa/PSMTabBarControl/PSMTabBarControl.m index 3c7271b40..865180417 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarControl.m +++ b/cocoa/PSMTabBarControl/PSMTabBarControl.m @@ -15,50 +15,48 @@ #import "PSMTabDragAssistant.h" #import "PSMTabBarController.h" -#include - @interface PSMTabBarControl (Private) - // constructor/destructor +// constructor/destructor - (void)initAddedProperties; - // accessors +// accessors - (NSEvent *)lastMouseDownEvent; - (void)setLastMouseDownEvent:(NSEvent *)event; - // contents +// contents - (void)addTabViewItem:(NSTabViewItem *)item; - (void)removeTabForCell:(PSMTabBarCell *)cell; - // draw +// draw - (void)update; - (void)update:(BOOL)animate; - (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell; - (void)_positionOverflowMenu; - (void)_checkWindowFrame; - // actions +// actions - (void)overflowMenuAction:(id)sender; - (void)closeTabClick:(id)sender; - (void)tabClick:(id)sender; - (void)tabNothing:(id)sender; - // notification handlers +// notification handlers - (void)frameDidChange:(NSNotification *)notification; - (void)windowDidMove:(NSNotification *)aNotification; - (void)windowDidUpdate:(NSNotification *)notification; - // NSTabView delegate +// NSTabView delegate - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem; - (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem; - (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem; - (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)tabView; - // archiving +// archiving - (void)encodeWithCoder:(NSCoder *)aCoder; - (id)initWithCoder:(NSCoder *)aDecoder; - // convenience +// convenience - (void)_bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item; - (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame; @@ -71,9 +69,11 @@ #pragma mark Characteristics + (NSBundle *)bundle; { - static NSBundle *bundle = nil; - if (!bundle) bundle = [NSBundle bundleForClass:[PSMTabBarControl class]]; - return bundle; + static NSBundle *bundle = nil; + if(!bundle) { + bundle = [NSBundle bundleForClass:[PSMTabBarControl class]]; + } + return bundle; } /*! @@ -81,11 +81,10 @@ @abstract The number of pixels available for cells @discussion Calculates the number of pixels available for cells based on margins and the window resize badge. @returns Returns the amount of space for cells. -*/ + */ -- (CGFloat)availableCellWidth -{ - return [self frame].size.width - [style leftMarginForTabBarControl] - [style rightMarginForTabBarControl] - _resizeAreaCompensation; +- (CGFloat)availableCellWidth { + return [self frame].size.width - [style leftMarginForTabBarControl] - [style rightMarginForTabBarControl] - _resizeAreaCompensation; } /*! @@ -93,114 +92,115 @@ @abstract The basic rect for a tab cell. @discussion Creates a generic frame for a tab cell based on the current control state. @returns Returns a basic rect for a tab cell. -*/ + */ -- (NSRect)genericCellRect -{ - NSRect aRect=[self frame]; - aRect.origin.x = [style leftMarginForTabBarControl]; - aRect.origin.y = 0.0; - aRect.size.width = [self availableCellWidth]; - aRect.size.height = [style tabCellHeight]; - return aRect; +- (NSRect)genericCellRect { + NSRect aRect = [self frame]; + aRect.origin.x = [style leftMarginForTabBarControl]; + aRect.origin.y = 0.0; + aRect.size.width = [self availableCellWidth]; + aRect.size.height = [style tabCellHeight]; + return aRect; } #pragma mark - #pragma mark Constructor/destructor -- (void)initAddedProperties -{ - _cells = [[NSMutableArray alloc] initWithCapacity:10]; +- (void)initAddedProperties { + _cells = [[NSMutableArray alloc] initWithCapacity:10]; _controller = [[PSMTabBarController alloc] initWithTabBarControl:self]; - _animationTimer = nil; - - // default config + _animationTimer = nil; + + // default config _currentStep = kPSMIsNotBeingResized; _orientation = PSMTabBarHorizontalOrientation; - _canCloseOnlyTab = NO; + _canCloseOnlyTab = NO; _disableTabClose = NO; - _showAddTabButton = NO; - _hideForSingleTab = NO; - _sizeCellsToFit = NO; - _isHidden = NO; - _awakenedFromNib = NO; + _showAddTabButton = NO; + _hideForSingleTab = NO; + _sizeCellsToFit = NO; + _isHidden = NO; + _awakenedFromNib = NO; _automaticallyAnimates = NO; - _useOverflowMenu = YES; + _useOverflowMenu = YES; _allowsBackgroundTabClosing = YES; _allowsResizing = NO; _selectsTabsOnMouseDown = NO; - _alwaysShowActiveTab = NO; + _alwaysShowActiveTab = NO; _allowsScrubbing = NO; - _cellMinWidth = 100; - _cellMaxWidth = 280; - _cellOptimumWidth = 130; + _cellMinWidth = 100; + _cellMaxWidth = 280; + _cellOptimumWidth = 130; _tearOffStyle = PSMTabBarTearOffAlphaWindow; - style = [[PSMUnifiedTabStyle alloc] init]; - - // the overflow button/menu - NSRect overflowButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 0, [style rightMarginForTabBarControl] - 1, [self frame].size.height); - _overflowPopUpButton = [[PSMOverflowPopUpButton alloc] initWithFrame:overflowButtonRect pullsDown:YES]; - [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin]; - [_overflowPopUpButton setHidden:YES]; - [self addSubview:_overflowPopUpButton]; - [self _positionOverflowMenu]; - - // new tab button - NSRect addTabButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 3.0, 16.0, 16.0); - _addTabButton = [[PSMRolloverButton alloc] initWithFrame:addTabButtonRect]; - if (_addTabButton) { - NSImage *newButtonImage = [style addTabButtonImage]; - if (newButtonImage) { - [_addTabButton setUsualImage:newButtonImage]; - } - newButtonImage = [style addTabButtonPressedImage]; - if (newButtonImage) { - [_addTabButton setAlternateImage:newButtonImage]; - } - newButtonImage = [style addTabButtonRolloverImage]; - if (newButtonImage) { - [_addTabButton setRolloverImage:newButtonImage]; - } - [_addTabButton setTitle:@""]; - [_addTabButton setImagePosition:NSImageOnly]; - [_addTabButton setButtonType:NSMomentaryChangeButton]; - [_addTabButton setBordered:NO]; - [_addTabButton setBezelStyle:NSShadowlessSquareBezelStyle]; - [self addSubview:_addTabButton]; - - if (_showAddTabButton) { - [_addTabButton setHidden:NO]; - } else { - [_addTabButton setHidden:YES]; - } - [_addTabButton setNeedsDisplay:YES]; - } -} - -- (id)initWithFrame:(NSRect)frame + style = [[[[self class] defaultStyleClass] alloc] init]; + + // the overflow button/menu + NSRect overflowButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 0, [style rightMarginForTabBarControl] - 1, [self frame].size.height); + _overflowPopUpButton = [[PSMOverflowPopUpButton alloc] initWithFrame:overflowButtonRect pullsDown:YES]; + [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin]; + [_overflowPopUpButton setHidden:YES]; + [self addSubview:_overflowPopUpButton]; + [self _positionOverflowMenu]; + + // new tab button + NSRect addTabButtonRect = NSMakeRect([self frame].size.width - [style rightMarginForTabBarControl] + 1, 3.0, 16.0, 16.0); + _addTabButton = [[PSMRolloverButton alloc] initWithFrame:addTabButtonRect]; + if(_addTabButton) { + NSImage *newButtonImage = [style addTabButtonImage]; + if(newButtonImage) { + [_addTabButton setUsualImage:newButtonImage]; + } + newButtonImage = [style addTabButtonPressedImage]; + if(newButtonImage) { + [_addTabButton setAlternateImage:newButtonImage]; + } + newButtonImage = [style addTabButtonRolloverImage]; + if(newButtonImage) { + [_addTabButton setRolloverImage:newButtonImage]; + } + [_addTabButton setTitle:@""]; + [_addTabButton setImagePosition:NSImageOnly]; + [_addTabButton setButtonType:NSMomentaryChangeButton]; + [_addTabButton setBordered:NO]; + [_addTabButton setBezelStyle:NSShadowlessSquareBezelStyle]; + [self addSubview:_addTabButton]; + + if(_showAddTabButton) { + [_addTabButton setHidden:NO]; + } else { + [_addTabButton setHidden:YES]; + } + [_addTabButton setNeedsDisplay:YES]; + } +} + ++ (Class) defaultStyleClass; { - self = [super initWithFrame:frame]; - if (self) { - // Initialization - [self initAddedProperties]; - [self registerForDraggedTypes:[NSArray arrayWithObjects:@"PSMTabBarControlItemPBType", nil]]; - + return [PSMUnifiedTabStyle class]; +} + +- (id)initWithFrame:(NSRect)frame { + self = [super initWithFrame:frame]; + if(self) { + // Initialization + [self initAddedProperties]; + [self registerForDraggedTypes:[NSArray arrayWithObjects:@"PSMTabBarControlItemPBType", nil]]; + // resize [self setPostsFrameChangedNotifications:YES]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification object:self]; - } - [self setTarget:self]; - return self; + } + [self setTarget:self]; + return self; } -- (void)dealloc -{ +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - + //stop any animations that may be running [_animationTimer invalidate]; [_animationTimer release]; _animationTimer = nil; - + [_showHideAnimationTimer invalidate]; [_showHideAnimationTimer release]; _showHideAnimationTimer = nil; @@ -210,538 +210,496 @@ //unbind all the items to prevent crashing //not sure if this is necessary or not - NSEnumerator *enumerator = [_cells objectEnumerator]; + // http://code.google.com/p/maccode/issues/detail?id=35 + NSEnumerator *enumerator = [[[_cells copy] autorelease] objectEnumerator]; PSMTabBarCell *nextCell; - while ( (nextCell = [enumerator nextObject]) ) { + while((nextCell = [enumerator nextObject])) { [self removeTabForCell:nextCell]; } - - [_overflowPopUpButton release]; - [_cells release]; + + [_overflowPopUpButton release]; + [_cells release]; [_controller release]; - [tabView release]; - [_addTabButton release]; - [partnerView release]; - [_lastMouseDownEvent release]; - [style release]; - - [self unregisterDraggedTypes]; - - [super dealloc]; + [tabView release]; + [_addTabButton release]; + [partnerView release]; + [_lastMouseDownEvent release]; + [style release]; + + [self unregisterDraggedTypes]; + + [super dealloc]; } -- (void)awakeFromNib -{ - // build cells from existing tab view items - NSArray *existingItems = [tabView tabViewItems]; - NSEnumerator *e = [existingItems objectEnumerator]; - NSTabViewItem *item; - while ( (item = [e nextObject]) ) { - if (![[self representedTabViewItems] containsObject:item]) { - [self addTabViewItem:item]; +- (void)awakeFromNib { + // build cells from existing tab view items + NSArray *existingItems = [tabView tabViewItems]; + NSEnumerator *e = [existingItems objectEnumerator]; + NSTabViewItem *item; + while((item = [e nextObject])) { + if(![[self representedTabViewItems] containsObject:item]) { + [self addTabViewItem:item]; } - } + } } - (void)viewWillMoveToWindow:(NSWindow *)aWindow { - NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; - + NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; + [center removeObserver:self name:NSWindowDidBecomeKeyNotification object:nil]; [center removeObserver:self name:NSWindowDidResignKeyNotification object:nil]; [center removeObserver:self name:NSWindowDidUpdateNotification object:nil]; [center removeObserver:self name:NSWindowDidMoveNotification object:nil]; - - if (_showHideAnimationTimer) { + + if(_showHideAnimationTimer) { [_showHideAnimationTimer invalidate]; [_showHideAnimationTimer release]; _showHideAnimationTimer = nil; } - - if (aWindow) { + + if(aWindow) { [center addObserver:self selector:@selector(windowStatusDidChange:) name:NSWindowDidBecomeKeyNotification object:aWindow]; [center addObserver:self selector:@selector(windowStatusDidChange:) name:NSWindowDidResignKeyNotification object:aWindow]; [center addObserver:self selector:@selector(windowDidUpdate:) name:NSWindowDidUpdateNotification object:aWindow]; [center addObserver:self selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:aWindow]; - } + } } -- (void)windowStatusDidChange:(NSNotification *)notification -{ +- (void)windowStatusDidChange:(NSNotification *)notification { [self setNeedsDisplay:YES]; } #pragma mark - #pragma mark Accessors -- (NSMutableArray *)cells -{ - return _cells; +- (NSMutableArray *)cells { + return _cells; } -- (NSEvent *)lastMouseDownEvent -{ - return _lastMouseDownEvent; +- (NSEvent *)lastMouseDownEvent { + return _lastMouseDownEvent; } -- (void)setLastMouseDownEvent:(NSEvent *)event -{ - [event retain]; - [_lastMouseDownEvent release]; - _lastMouseDownEvent = event; +- (void)setLastMouseDownEvent:(NSEvent *)event { + [event retain]; + [_lastMouseDownEvent release]; + _lastMouseDownEvent = event; } -- (id)delegate -{ - return delegate; +- (id)delegate { + return delegate; } -- (void)setDelegate:(id)object -{ - delegate = object; - +- (void)setDelegate:(id)object { + delegate = object; + NSMutableArray *types = [NSMutableArray arrayWithObject:@"PSMTabBarControlItemPBType"]; - + //Update the allowed drag types - if ([self delegate] && [[self delegate] respondsToSelector:@selector(allowedDraggedTypesForTabView:)]) { + if([self delegate] && [[self delegate] respondsToSelector:@selector(allowedDraggedTypesForTabView:)]) { [types addObjectsFromArray:[[self delegate] allowedDraggedTypesForTabView:tabView]]; } [self unregisterDraggedTypes]; [self registerForDraggedTypes:types]; } -- (NSTabView *)tabView -{ - return tabView; +- (NSTabView *)tabView { + return tabView; } -- (void)setTabView:(NSTabView *)view -{ - [view retain]; - [tabView release]; - tabView = view; +- (void)setTabView:(NSTabView *)view { + [view retain]; + [tabView release]; + tabView = view; } -- (id)style -{ - return style; +- (id)style { + return style; } -- (NSString *)styleName -{ - return [style name]; +- (NSString *)styleName { + return [style name]; } -- (void)setStyle:(id )newStyle -{ - if (style != newStyle) { - [style autorelease]; - style = [newStyle retain]; - - // restyle add tab button - if (_addTabButton) { - NSImage *newButtonImage = [style addTabButtonImage]; - if (newButtonImage) { - [_addTabButton setUsualImage:newButtonImage]; - } - - newButtonImage = [style addTabButtonPressedImage]; - if (newButtonImage) { - [_addTabButton setAlternateImage:newButtonImage]; - } - - newButtonImage = [style addTabButtonRolloverImage]; - if (newButtonImage) { - [_addTabButton setRolloverImage:newButtonImage]; - } - } - - [self update]; - } -} - -- (void)setStyleNamed:(NSString *)name -{ - id newStyle = [[PSMUnifiedTabStyle alloc] init]; - [self setStyle:newStyle]; - [newStyle release]; +- (void)setStyle:(id )newStyle { + if(style != newStyle) { + [style autorelease]; + style = [newStyle retain]; + + // restyle add tab button + if(_addTabButton) { + NSImage *newButtonImage = [style addTabButtonImage]; + if(newButtonImage) { + [_addTabButton setUsualImage:newButtonImage]; + } + + newButtonImage = [style addTabButtonPressedImage]; + if(newButtonImage) { + [_addTabButton setAlternateImage:newButtonImage]; + } + + newButtonImage = [style addTabButtonRolloverImage]; + if(newButtonImage) { + [_addTabButton setRolloverImage:newButtonImage]; + } + } + + [self update]; + } } -- (PSMTabBarOrientation)orientation -{ +- (void)setStyleNamed:(NSString *)name { + + Class styleClass = NSClassFromString( [NSString stringWithFormat: @"PSM%@TabStyle", [name capitalizedString]] ); + if (styleClass == Nil) styleClass = [isa defaultStyleClass]; + + id newStyle = [[styleClass alloc] init]; + [self setStyle:newStyle]; + [newStyle release]; +} + +- (PSMTabBarOrientation)orientation { return _orientation; } -- (void)setOrientation:(PSMTabBarOrientation)value -{ +- (void)setOrientation:(PSMTabBarOrientation)value { PSMTabBarOrientation lastOrientation = _orientation; _orientation = value; - if (_tabBarWidth < 10) { + if(_tabBarWidth < 10) { _tabBarWidth = 120; } - - if (lastOrientation != _orientation) { + + if(lastOrientation != _orientation) { [[self style] setOrientation:_orientation]; - [self _positionOverflowMenu]; //move the overflow popup button to the right place + [self _positionOverflowMenu]; //move the overflow popup button to the right place [self update:NO]; } } -- (BOOL)canCloseOnlyTab -{ - return _canCloseOnlyTab; +- (BOOL)canCloseOnlyTab { + return _canCloseOnlyTab; } -- (void)setCanCloseOnlyTab:(BOOL)value -{ - _canCloseOnlyTab = value; - if ([_cells count] == 1) { - [self update]; - } +- (void)setCanCloseOnlyTab:(BOOL)value { + _canCloseOnlyTab = value; + if([_cells count] == 1) { + [self update]; + } } -- (BOOL)disableTabClose -{ +- (BOOL)disableTabClose { return _disableTabClose; } -- (void)setDisableTabClose:(BOOL)value -{ +- (void)setDisableTabClose:(BOOL)value { _disableTabClose = value; [self update]; } -- (BOOL)hideForSingleTab -{ - return _hideForSingleTab; +- (BOOL)hideForSingleTab { + return _hideForSingleTab; } -- (void)setHideForSingleTab:(BOOL)value -{ - _hideForSingleTab = value; - [self update]; +- (void)setHideForSingleTab:(BOOL)value { + _hideForSingleTab = value; + [self update]; } -- (BOOL)showAddTabButton -{ - return _showAddTabButton; +- (BOOL)showAddTabButton { + return _showAddTabButton; } -- (void)setShowAddTabButton:(BOOL)value -{ - _showAddTabButton = value; - if (!NSIsEmptyRect([_controller addButtonRect])) +- (void)setShowAddTabButton:(BOOL)value { + _showAddTabButton = value; + if(!NSIsEmptyRect([_controller addButtonRect])) { [_addTabButton setFrame:[_controller addButtonRect]]; + } - [_addTabButton setHidden:!_showAddTabButton]; + [_addTabButton setHidden:!_showAddTabButton]; [_addTabButton setNeedsDisplay:YES]; [self update]; } -- (NSInteger)cellMinWidth -{ - return _cellMinWidth; +- (NSInteger)cellMinWidth { + return _cellMinWidth; } -- (void)setCellMinWidth:(NSInteger)value -{ - _cellMinWidth = value; - [self update]; +- (void)setCellMinWidth:(NSInteger)value { + _cellMinWidth = value; + [self update]; } -- (NSInteger)cellMaxWidth -{ - return _cellMaxWidth; +- (NSInteger)cellMaxWidth { + return _cellMaxWidth; } -- (void)setCellMaxWidth:(NSInteger)value -{ - _cellMaxWidth = value; - [self update]; +- (void)setCellMaxWidth:(NSInteger)value { + _cellMaxWidth = value; + [self update]; } -- (NSInteger)cellOptimumWidth -{ - return _cellOptimumWidth; +- (NSInteger)cellOptimumWidth { + return _cellOptimumWidth; } -- (void)setCellOptimumWidth:(NSInteger)value -{ - _cellOptimumWidth = value; - [self update]; +- (void)setCellOptimumWidth:(NSInteger)value { + _cellOptimumWidth = value; + [self update]; } -- (BOOL)sizeCellsToFit -{ - return _sizeCellsToFit; +- (BOOL)sizeCellsToFit { + return _sizeCellsToFit; } -- (void)setSizeCellsToFit:(BOOL)value -{ - _sizeCellsToFit = value; - [self update]; +- (void)setSizeCellsToFit:(BOOL)value { + _sizeCellsToFit = value; + [self update]; } -- (BOOL)useOverflowMenu -{ - return _useOverflowMenu; +- (BOOL)useOverflowMenu { + return _useOverflowMenu; } -- (void)setUseOverflowMenu:(BOOL)value -{ - _useOverflowMenu = value; - [self update]; +- (void)setUseOverflowMenu:(BOOL)value { + _useOverflowMenu = value; + [self update]; } -- (PSMRolloverButton *)addTabButton -{ - return _addTabButton; +- (PSMRolloverButton *)addTabButton { + return _addTabButton; } -- (PSMOverflowPopUpButton *)overflowPopUpButton -{ - return _overflowPopUpButton; +- (PSMOverflowPopUpButton *)overflowPopUpButton { + return _overflowPopUpButton; } -- (BOOL)allowsBackgroundTabClosing -{ +- (BOOL)allowsBackgroundTabClosing { return _allowsBackgroundTabClosing; } -- (void)setAllowsBackgroundTabClosing:(BOOL)value -{ +- (void)setAllowsBackgroundTabClosing:(BOOL)value { _allowsBackgroundTabClosing = value; } -- (BOOL)allowsResizing -{ +- (BOOL)allowsResizing { return _allowsResizing; } -- (void)setAllowsResizing:(BOOL)value -{ +- (void)setAllowsResizing:(BOOL)value { _allowsResizing = value; } -- (BOOL)selectsTabsOnMouseDown -{ +- (BOOL)selectsTabsOnMouseDown { return _selectsTabsOnMouseDown; } -- (void)setSelectsTabsOnMouseDown:(BOOL)value -{ +- (void)setSelectsTabsOnMouseDown:(BOOL)value { _selectsTabsOnMouseDown = value; } -- (BOOL)automaticallyAnimates -{ +- (BOOL)automaticallyAnimates { return _automaticallyAnimates; } -- (void)setAutomaticallyAnimates:(BOOL)value -{ +- (void)setAutomaticallyAnimates:(BOOL)value { _automaticallyAnimates = value; } -- (BOOL)alwaysShowActiveTab -{ +- (BOOL)alwaysShowActiveTab { return _alwaysShowActiveTab; } -- (void)setAlwaysShowActiveTab:(BOOL)value -{ +- (void)setAlwaysShowActiveTab:(BOOL)value { _alwaysShowActiveTab = value; } -- (BOOL)allowsScrubbing -{ +- (BOOL)allowsScrubbing { return _allowsScrubbing; } -- (void)setAllowsScrubbing:(BOOL)value -{ +- (void)setAllowsScrubbing:(BOOL)value { _allowsScrubbing = value; } -- (PSMTabBarTearOffStyle)tearOffStyle -{ +- (PSMTabBarTearOffStyle)tearOffStyle { return _tearOffStyle; } -- (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle -{ +- (void)setTearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle { _tearOffStyle = tearOffStyle; } #pragma mark - #pragma mark Functionality -- (void)addTabViewItem:(NSTabViewItem *)item -{ - // create cell - PSMTabBarCell *cell = [[PSMTabBarCell alloc] initWithControlView:self]; - NSRect cellRect, lastCellFrame = [[_cells lastObject] frame]; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { +- (void)addTabViewItem:(NSTabViewItem *)item { + // create cell + PSMTabBarCell *cell = [[PSMTabBarCell alloc] initWithControlView:self]; + NSRect cellRect, lastCellFrame; + if([_cells lastObject] != nil) { + cellRect = lastCellFrame = [[_cells lastObject] frame]; + } else { + cellRect = lastCellFrame = NSZeroRect; + } + + if([self orientation] == PSMTabBarHorizontalOrientation) { cellRect = [self genericCellRect]; cellRect.size.width = 30; cellRect.origin.x = lastCellFrame.origin.x + lastCellFrame.size.width; } else { - cellRect = /*lastCellFrame*/[self genericCellRect]; + cellRect = /*lastCellFrame*/ [self genericCellRect]; cellRect.size.width = lastCellFrame.size.width; cellRect.size.height = 0; cellRect.origin.y = lastCellFrame.origin.y + lastCellFrame.size.height; } - - [cell setRepresentedObject:item]; + + [cell setRepresentedObject:item]; [cell setFrame:cellRect]; - - // bind it up - [self bindPropertiesForCell:cell andTabViewItem:item]; - - // add to collection - [_cells addObject:cell]; - [cell release]; - if ([_cells count] == [tabView numberOfTabViewItems]) { - [self update]; // don't update unless all are accounted for! + + // bind it up + [self bindPropertiesForCell:cell andTabViewItem:item]; + + // add to collection + [_cells addObject:cell]; + [cell release]; + if([_cells count] == [tabView numberOfTabViewItems]) { + [self update]; // don't update unless all are accounted for! } } -- (void)removeTabForCell:(PSMTabBarCell *)cell -{ +- (void)removeTabForCell:(PSMTabBarCell *)cell { NSTabViewItem *item = [cell representedObject]; - - // unbind - [[cell indicator] unbind:@"animate"]; - [[cell indicator] unbind:@"hidden"]; - [cell unbind:@"hasIcon"]; - [cell unbind:@"hasLargeImage"]; - [cell unbind:@"title"]; - [cell unbind:@"count"]; + + // unbind + [[cell indicator] unbind:@"animate"]; + [[cell indicator] unbind:@"hidden"]; + [cell unbind:@"hasIcon"]; + [cell unbind:@"hasLargeImage"]; + [cell unbind:@"title"]; + [cell unbind:@"count"]; [cell unbind:@"countColor"]; - [cell unbind:@"isEdited"]; + [cell unbind:@"isEdited"]; - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(isProcessing)]) { + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(isProcessing)]) { [[item identifier] removeObserver:cell forKeyPath:@"isProcessing"]; } } - - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(icon)]) { + + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(icon)]) { [[item identifier] removeObserver:cell forKeyPath:@"icon"]; } } - - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(objectCount)]) { + + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(objectCount)]) { [[item identifier] removeObserver:cell forKeyPath:@"objectCount"]; } } - - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(countColor)]) { + + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(countColor)]) { [[item identifier] removeObserver:cell forKeyPath:@"countColor"]; } } - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(largeImage)]) { + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(largeImage)]) { [[item identifier] removeObserver:cell forKeyPath:@"largeImage"]; } } - - if ([item identifier] != nil) { - if ([[item identifier] respondsToSelector:@selector(isEdited)]) { + + if([item identifier] != nil) { + if([[item identifier] respondsToSelector:@selector(isEdited)]) { [[item identifier] removeObserver:cell forKeyPath:@"isEdited"]; } } - - // stop watching identifier - [item removeObserver:self forKeyPath:@"identifier"]; - - // remove indicator - if ([[self subviews] containsObject:[cell indicator]]) { - [[cell indicator] removeFromSuperview]; - } - // remove tracking - [[NSNotificationCenter defaultCenter] removeObserver:cell]; - - if ([cell closeButtonTrackingTag] != 0) { - [self removeTrackingRect:[cell closeButtonTrackingTag]]; + + // stop watching identifier + [item removeObserver:self forKeyPath:@"identifier"]; + + // remove indicator + if([[self subviews] containsObject:[cell indicator]]) { + [[cell indicator] removeFromSuperview]; + } + // remove tracking + [[NSNotificationCenter defaultCenter] removeObserver:cell]; + + if([cell closeButtonTrackingTag] != 0) { + [self removeTrackingRect:[cell closeButtonTrackingTag]]; [cell setCloseButtonTrackingTag:0]; - } - if ([cell cellTrackingTag] != 0) { - [self removeTrackingRect:[cell cellTrackingTag]]; + } + if([cell cellTrackingTag] != 0) { + [self removeTrackingRect:[cell cellTrackingTag]]; [cell setCellTrackingTag:0]; - } + } - // pull from collection - [_cells removeObject:cell]; + // pull from collection + [_cells removeObject:cell]; - [self update]; + [self update]; } -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - // did the tab's identifier change? - if ([keyPath isEqualToString:@"identifier"]) { - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - if ([cell representedObject] == object) { - [self _bindPropertiesForCell:cell andTabViewItem:object]; +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { + // did the tab's identifier change? + if([keyPath isEqualToString:@"identifier"]) { + NSEnumerator *e = [_cells objectEnumerator]; + PSMTabBarCell *cell; + while((cell = [e nextObject])) { + if([cell representedObject] == object) { + [self _bindPropertiesForCell:cell andTabViewItem:object]; } - } - } + } + } } #pragma mark - #pragma mark Hide/Show -- (void)hideTabBar:(BOOL)hide animate:(BOOL)animate -{ - if (!_awakenedFromNib || (_isHidden && hide) || (!_isHidden && !hide) || (_currentStep != kPSMIsNotBeingResized)) { - return; +- (void)hideTabBar:(BOOL)hide animate:(BOOL)animate { + if(!_awakenedFromNib || (_isHidden && hide) || (!_isHidden && !hide) || (_currentStep != kPSMIsNotBeingResized)) { + return; } - - [[self subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; - _isHidden = hide; - _currentStep = 0; - if (!animate) { - _currentStep = (NSInteger)kPSMHideAnimationSteps; + [[self subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)]; + + _isHidden = hide; + _currentStep = 0; + if(!animate) { + _currentStep = (NSInteger)kPSMHideAnimationSteps; } - if (hide) { + if(hide) { [_overflowPopUpButton removeFromSuperview]; [_addTabButton removeFromSuperview]; - } else if (!animate) { + } else if(!animate) { [self addSubview:_overflowPopUpButton]; [self addSubview:_addTabButton]; } - CGFloat partnerOriginalSize, partnerOriginalOrigin, myOriginalSize, myOriginalOrigin, partnerTargetSize, partnerTargetOrigin, myTargetSize, myTargetOrigin; - - // target values for partner - if ([self orientation] == PSMTabBarHorizontalOrientation) { + CGFloat partnerOriginalSize, partnerOriginalOrigin, myOriginalSize, myOriginalOrigin, partnerTargetSize, partnerTargetOrigin, myTargetSize, myTargetOrigin; + + // target values for partner + if([self orientation] == PSMTabBarHorizontalOrientation) { // current (original) values myOriginalSize = [self frame].size.height; myOriginalOrigin = [self frame].origin.y; - if (partnerView) { + if(partnerView) { partnerOriginalSize = [partnerView frame].size.height; partnerOriginalOrigin = [partnerView frame].origin.y; } else { partnerOriginalSize = [[self window] frame].size.height; partnerOriginalOrigin = [[self window] frame].origin.y; } - - if (partnerView) { + + if(partnerView) { // above or below me? - if ((myOriginalOrigin - 22) > partnerOriginalOrigin) { + if((myOriginalOrigin - 22) > partnerOriginalOrigin) { // partner is below me - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin + 21; myTargetSize = myOriginalSize - 21; @@ -756,7 +714,7 @@ } } else { // partner is above me - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin; myTargetSize = myOriginalSize - 21; @@ -772,7 +730,7 @@ } } else { // for window movement - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin; myTargetSize = myOriginalSize - 21; @@ -786,23 +744,23 @@ partnerTargetSize = partnerOriginalSize + 21; } } - } else /* vertical */ { - // current (original) values + } else { /* vertical */ + // current (original) values myOriginalSize = [self frame].size.width; myOriginalOrigin = [self frame].origin.x; - if (partnerView) { + if(partnerView) { partnerOriginalSize = [partnerView frame].size.width; partnerOriginalOrigin = [partnerView frame].origin.x; } else { partnerOriginalSize = [[self window] frame].size.width; partnerOriginalOrigin = [[self window] frame].origin.x; } - - if (partnerView) { + + if(partnerView) { //to the left or right? - if (myOriginalOrigin < partnerOriginalOrigin + partnerOriginalSize) { + if(myOriginalOrigin < partnerOriginalOrigin + partnerOriginalSize) { // partner is to the left - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin; myTargetSize = 1; @@ -818,7 +776,7 @@ } } else { // partner is to the right - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin + myOriginalSize; myTargetSize = 1; @@ -835,7 +793,7 @@ } } else { // for window movement - if (_isHidden) { + if(_isHidden) { // I'm shrinking myTargetOrigin = myOriginalOrigin; myTargetSize = 1; @@ -850,211 +808,201 @@ partnerTargetSize = partnerOriginalSize + _tabBarWidth - 1; } } - - if (!_isHidden && [[self delegate] respondsToSelector:@selector(desiredWidthForVerticalTabBar:)]) + + if(!_isHidden && [[self delegate] respondsToSelector:@selector(desiredWidthForVerticalTabBar:)]) { myTargetSize = [[self delegate] desiredWidthForVerticalTabBar:self]; + } } - NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:myOriginalOrigin], @"myOriginalOrigin", [NSNumber numberWithDouble:partnerOriginalOrigin], @"partnerOriginalOrigin", [NSNumber numberWithDouble:myOriginalSize], @"myOriginalSize", [NSNumber numberWithDouble:partnerOriginalSize], @"partnerOriginalSize", [NSNumber numberWithDouble:myTargetOrigin], @"myTargetOrigin", [NSNumber numberWithDouble:partnerTargetOrigin], @"partnerTargetOrigin", [NSNumber numberWithDouble:myTargetSize], @"myTargetSize", [NSNumber numberWithDouble:partnerTargetSize], @"partnerTargetSize", nil]; - if (_showHideAnimationTimer) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:myOriginalOrigin], @"myOriginalOrigin", [NSNumber numberWithDouble:partnerOriginalOrigin], @"partnerOriginalOrigin", [NSNumber numberWithDouble:myOriginalSize], @"myOriginalSize", [NSNumber numberWithDouble:partnerOriginalSize], @"partnerOriginalSize", [NSNumber numberWithDouble:myTargetOrigin], @"myTargetOrigin", [NSNumber numberWithDouble:partnerTargetOrigin], @"partnerTargetOrigin", [NSNumber numberWithDouble:myTargetSize], @"myTargetSize", [NSNumber numberWithDouble:partnerTargetSize], @"partnerTargetSize", nil]; + if(_showHideAnimationTimer) { [_showHideAnimationTimer invalidate]; [_showHideAnimationTimer release]; } - _showHideAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:(1.0 / 30.0) target:self selector:@selector(animateShowHide:) userInfo:userInfo repeats:YES] retain]; + _showHideAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:(1.0 / 30.0) target:self selector:@selector(animateShowHide:) userInfo:userInfo repeats:YES] retain]; } -- (void)animateShowHide:(NSTimer *)timer -{ - // moves the frame of the tab bar and window (or partner view) linearly to hide or show the tab bar - NSRect myFrame = [self frame]; +- (void)animateShowHide:(NSTimer *)timer { + // moves the frame of the tab bar and window (or partner view) linearly to hide or show the tab bar + NSRect myFrame = [self frame]; NSDictionary *userInfo = [timer userInfo]; - CGFloat myCurrentOrigin = ([[userInfo objectForKey:@"myOriginalOrigin"] doubleValue] + (([[userInfo objectForKey:@"myTargetOrigin"] doubleValue] - [[userInfo objectForKey:@"myOriginalOrigin"] doubleValue]) * (_currentStep/kPSMHideAnimationSteps))); - CGFloat myCurrentSize = ([[userInfo objectForKey:@"myOriginalSize"] doubleValue] + (([[userInfo objectForKey:@"myTargetSize"] doubleValue] - [[userInfo objectForKey:@"myOriginalSize"] doubleValue]) * (_currentStep/kPSMHideAnimationSteps))); - CGFloat partnerCurrentOrigin = ([[userInfo objectForKey:@"partnerOriginalOrigin"] doubleValue] + (([[userInfo objectForKey:@"partnerTargetOrigin"] doubleValue] - [[userInfo objectForKey:@"partnerOriginalOrigin"] doubleValue]) * (_currentStep/kPSMHideAnimationSteps))); - CGFloat partnerCurrentSize = ([[userInfo objectForKey:@"partnerOriginalSize"] doubleValue] + (([[userInfo objectForKey:@"partnerTargetSize"] doubleValue] - [[userInfo objectForKey:@"partnerOriginalSize"] doubleValue]) * (_currentStep/kPSMHideAnimationSteps))); - + CGFloat myCurrentOrigin = ([[userInfo objectForKey:@"myOriginalOrigin"] doubleValue] + (([[userInfo objectForKey:@"myTargetOrigin"] doubleValue] - [[userInfo objectForKey:@"myOriginalOrigin"] doubleValue]) * (_currentStep / kPSMHideAnimationSteps))); + CGFloat myCurrentSize = ([[userInfo objectForKey:@"myOriginalSize"] doubleValue] + (([[userInfo objectForKey:@"myTargetSize"] doubleValue] - [[userInfo objectForKey:@"myOriginalSize"] doubleValue]) * (_currentStep / kPSMHideAnimationSteps))); + CGFloat partnerCurrentOrigin = ([[userInfo objectForKey:@"partnerOriginalOrigin"] doubleValue] + (([[userInfo objectForKey:@"partnerTargetOrigin"] doubleValue] - [[userInfo objectForKey:@"partnerOriginalOrigin"] doubleValue]) * (_currentStep / kPSMHideAnimationSteps))); + CGFloat partnerCurrentSize = ([[userInfo objectForKey:@"partnerOriginalSize"] doubleValue] + (([[userInfo objectForKey:@"partnerTargetSize"] doubleValue] - [[userInfo objectForKey:@"partnerOriginalSize"] doubleValue]) * (_currentStep / kPSMHideAnimationSteps))); + NSRect myNewFrame; - if ([self orientation] == PSMTabBarHorizontalOrientation) { + if([self orientation] == PSMTabBarHorizontalOrientation) { myNewFrame = NSMakeRect(myFrame.origin.x, myCurrentOrigin, myFrame.size.width, myCurrentSize); } else { myNewFrame = NSMakeRect(myCurrentOrigin, myFrame.origin.y, myCurrentSize, myFrame.size.height); } - - if (partnerView) { - // resize self and view + + if(partnerView) { + // resize self and view NSRect resizeRect; - if ([self orientation] == PSMTabBarHorizontalOrientation) { + if([self orientation] == PSMTabBarHorizontalOrientation) { resizeRect = NSMakeRect([partnerView frame].origin.x, partnerCurrentOrigin, [partnerView frame].size.width, partnerCurrentSize); } else { resizeRect = NSMakeRect(partnerCurrentOrigin, [partnerView frame].origin.y, partnerCurrentSize, [partnerView frame].size.height); } [partnerView setFrame:resizeRect]; - [partnerView setNeedsDisplay:YES]; - [self setFrame:myNewFrame]; - } else { - // resize self and window + [partnerView setNeedsDisplay:YES]; + [self setFrame:myNewFrame]; + } else { + // resize self and window NSRect resizeRect; - if ([self orientation] == PSMTabBarHorizontalOrientation) { + if([self orientation] == PSMTabBarHorizontalOrientation) { resizeRect = NSMakeRect([[self window] frame].origin.x, partnerCurrentOrigin, [[self window] frame].size.width, partnerCurrentSize); } else { resizeRect = NSMakeRect(partnerCurrentOrigin, [[self window] frame].origin.y, partnerCurrentSize, [[self window] frame].size.height); } - [[self window] setFrame:resizeRect display:YES]; - [self setFrame:myNewFrame]; - } - - // next - _currentStep++; - if (_currentStep == kPSMHideAnimationSteps + 1) { + [[self window] setFrame:resizeRect display:YES]; + [self setFrame:myNewFrame]; + } + + // next + _currentStep++; + if(_currentStep == kPSMHideAnimationSteps + 1) { _currentStep = kPSMIsNotBeingResized; - [self viewDidEndLiveResize]; - [self update:NO]; - + [self viewDidEndLiveResize]; + [self update:NO]; + //send the delegate messages - if (_isHidden) { - if ([[self delegate] respondsToSelector:@selector(tabView:tabBarDidHide:)]) { + if(_isHidden) { + if([[self delegate] respondsToSelector:@selector(tabView:tabBarDidHide:)]) { [[self delegate] tabView:[self tabView] tabBarDidHide:self]; } } else { [self addSubview:_overflowPopUpButton]; [self addSubview:_addTabButton]; - if ([[self delegate] respondsToSelector:@selector(tabView:tabBarDidUnhide:)]) { + if([[self delegate] respondsToSelector:@selector(tabView:tabBarDidUnhide:)]) { [[self delegate] tabView:[self tabView] tabBarDidUnhide:self]; } } - + [_showHideAnimationTimer invalidate]; [_showHideAnimationTimer release]; _showHideAnimationTimer = nil; - } - [[self window] display]; + } + [[self window] display]; } -- (BOOL)isTabBarHidden -{ +- (BOOL)isTabBarHidden { return _isHidden; } -- (BOOL)isAnimating -{ - return _animationTimer != nil; +- (BOOL)isAnimating { + return _animationTimer != nil; } -- (id)partnerView -{ - return partnerView; +- (id)partnerView { + return partnerView; } -- (void)setPartnerView:(id)view -{ - [partnerView release]; - [view retain]; - partnerView = view; +- (void)setPartnerView:(id)view { + [partnerView release]; + [view retain]; + partnerView = view; } #pragma mark - #pragma mark Drawing -- (BOOL)isFlipped -{ - return YES; +- (BOOL)isFlipped { + return YES; } -- (void)drawRect:(NSRect)rect -{ - [style drawTabBar:self inRect:rect]; +- (void)drawRect:(NSRect)rect { + [style drawTabBar:self inRect:rect]; } -- (void)update -{ +- (void)update { [self update:_automaticallyAnimates]; } -- (void)update:(BOOL)animate -{ - // make sure all of our tabs are accounted for before updating - if ([[self tabView] numberOfTabViewItems] != [_cells count]) { - return; - } - - // hide/show? (these return if already in desired state) - if ( (_hideForSingleTab) && ([_cells count] <= 1) ) { - [self hideTabBar:YES animate:YES]; - return; - } else { - [self hideTabBar:NO animate:YES]; - } - - [self removeAllToolTips]; - [_controller layoutCells]; //eventually we should only have to call this when we know something has changed - - PSMTabBarCell *currentCell; - - NSMenu *overflowMenu = [_controller overflowMenu]; - [_overflowPopUpButton setHidden:(overflowMenu == nil)]; - [_overflowPopUpButton setMenu:overflowMenu]; - - if (_animationTimer) { +- (void)update:(BOOL)animate { + // make sure all of our tabs are accounted for before updating + if([[self tabView] numberOfTabViewItems] != [_cells count]) { + return; + } + + // hide/show? (these return if already in desired state) + if((_hideForSingleTab) && ([_cells count] <= 1)) { + [self hideTabBar:YES animate:YES]; + return; + } else { + [self hideTabBar:NO animate:YES]; + } + + [self removeAllToolTips]; + [_controller layoutCells]; //eventually we should only have to call this when we know something has changed + + PSMTabBarCell *currentCell; + + NSMenu *overflowMenu = [_controller overflowMenu]; + [_overflowPopUpButton setHidden:(overflowMenu == nil)]; + [_overflowPopUpButton setMenu:overflowMenu]; + + if(_animationTimer) { [_animationTimer invalidate]; [_animationTimer release]; _animationTimer = nil; - } - - if (animate) { - NSMutableArray *targetFrames = [NSMutableArray arrayWithCapacity:[_cells count]]; - - for (NSUInteger i = 0; i < [_cells count]; i++) { - currentCell = [_cells objectAtIndex:i]; - - //we're going from NSRect -> NSValue -> NSRect -> NSValue here - oh well - [targetFrames addObject:[NSValue valueWithRect:[_controller cellFrameAtIndex:i]]]; - } - - [_addTabButton setHidden:!_showAddTabButton]; - - NSAnimation *animation = [[NSAnimation alloc] initWithDuration:0.50 animationCurve:NSAnimationEaseInOut]; - [animation setAnimationBlockingMode:NSAnimationNonblocking]; - [animation startAnimation]; - _animationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 - target:self - selector:@selector(_animateCells:) - userInfo:[NSArray arrayWithObjects:targetFrames, animation, nil] - repeats:YES] retain]; + } + + if(animate) { + NSMutableArray *targetFrames = [NSMutableArray arrayWithCapacity:[_cells count]]; + + for(NSInteger i = 0; i < [_cells count]; i++) { + currentCell = [_cells objectAtIndex:i]; + + //we're going from NSRect -> NSValue -> NSRect -> NSValue here - oh well + [targetFrames addObject:[NSValue valueWithRect:[_controller cellFrameAtIndex:i]]]; + } + + [_addTabButton setHidden:!_showAddTabButton]; + + NSAnimation *animation = [[NSAnimation alloc] initWithDuration:0.50 animationCurve:NSAnimationEaseInOut]; + [animation setAnimationBlockingMode:NSAnimationNonblocking]; + [animation startAnimation]; + _animationTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 + target:self + selector:@selector(_animateCells:) + userInfo:[NSArray arrayWithObjects:targetFrames, animation, nil] + repeats:YES] retain]; [animation release]; [[NSRunLoop currentRunLoop] addTimer:_animationTimer forMode:NSEventTrackingRunLoopMode]; [self _animateCells:_animationTimer]; + } else { + for(NSInteger i = 0; i < [_cells count]; i++) { + currentCell = [_cells objectAtIndex:i]; + [currentCell setFrame:[_controller cellFrameAtIndex:i]]; - } else { - for (NSUInteger i = 0; i < [_cells count]; i++) { - currentCell = [_cells objectAtIndex:i]; - [currentCell setFrame:[_controller cellFrameAtIndex:i]]; - - if (![currentCell isInOverflowMenu]) { - [self _setupTrackingRectsForCell:currentCell]; - } - } - - [_addTabButton setFrame:[_controller addButtonRect]]; - [_addTabButton setHidden:!_showAddTabButton]; - [self setNeedsDisplay:YES]; - } -} - -- (void)_animateCells:(NSTimer *)timer -{ - NSAnimation *animation = [[timer userInfo] objectAtIndex:1]; + if(![currentCell isInOverflowMenu]) { + [self _setupTrackingRectsForCell:currentCell]; + } + } + + [_addTabButton setFrame:[_controller addButtonRect]]; + [_addTabButton setHidden:!_showAddTabButton]; + [self setNeedsDisplay:YES]; + } +} + +- (void)_animateCells:(NSTimer *)timer { + NSAnimation *animation = [[timer userInfo] objectAtIndex:1]; NSArray *targetFrames = [[timer userInfo] objectAtIndex:0]; - PSMTabBarCell *currentCell; + PSMTabBarCell *currentCell; NSInteger cellCount = [_cells count]; - - if ((cellCount > 0) && [animation isAnimating]) { + + if((cellCount > 0) && [animation isAnimating]) { //compare our target position with the current position and move towards the target - for (NSUInteger i = 0; i < [targetFrames count] && i < cellCount; i++) { + for(NSInteger i = 0; i < [targetFrames count] && i < cellCount; i++) { currentCell = [_cells objectAtIndex:i]; NSRect cellFrame = [currentCell frame], targetFrame = [[targetFrames objectAtIndex:i] rectValue]; CGFloat sizeChange; CGFloat originChange; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { + + if([self orientation] == PSMTabBarHorizontalOrientation) { sizeChange = (targetFrame.size.width - cellFrame.size.width) * [animation currentProgress]; originChange = (targetFrame.origin.x - cellFrame.origin.x) * [animation currentProgress]; cellFrame.size.width += sizeChange; @@ -1065,108 +1013,106 @@ cellFrame.size.height += sizeChange; cellFrame.origin.y += originChange; } - + [currentCell setFrame:cellFrame]; - + //highlight the cell if the mouse is over it NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; NSRect closeRect = [currentCell closeButtonRectForFrame:cellFrame]; [currentCell setHighlighted:NSMouseInRect(mousePoint, cellFrame, [self isFlipped])]; [currentCell setCloseButtonOver:NSMouseInRect(mousePoint, closeRect, [self isFlipped])]; } - - if (_showAddTabButton) { - //animate the add tab button - NSRect target = [_controller addButtonRect], frame = [_addTabButton frame]; - frame.origin.x += (target.origin.x - frame.origin.x) * [animation currentProgress]; - [_addTabButton setFrame:frame]; - } - } else { + + if(_showAddTabButton) { + //animate the add tab button + NSRect target = [_controller addButtonRect], frame = [_addTabButton frame]; + frame.origin.x += (target.origin.x - frame.origin.x) * [animation currentProgress]; + [_addTabButton setFrame:frame]; + } + } else { //put all the cells where they should be in their final position - if (cellCount > 0) { - for (NSUInteger i = 0; i < [targetFrames count] && i < cellCount; i++) { + if(cellCount > 0) { + for(NSInteger i = 0; i < [targetFrames count] && i < cellCount; i++) { PSMTabBarCell *currentCell = [_cells objectAtIndex:i]; NSRect cellFrame = [currentCell frame], targetFrame = [[targetFrames objectAtIndex:i] rectValue]; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { - cellFrame.size.width = targetFrame.size.width; - cellFrame.origin.x = targetFrame.origin.x; - } else { - cellFrame.size.height = targetFrame.size.height; - cellFrame.origin.y = targetFrame.origin.y; - } - + + if([self orientation] == PSMTabBarHorizontalOrientation) { + cellFrame.size.width = targetFrame.size.width; + cellFrame.origin.x = targetFrame.origin.x; + } else { + cellFrame.size.height = targetFrame.size.height; + cellFrame.origin.y = targetFrame.origin.y; + } + [currentCell setFrame:cellFrame]; - - //highlight the cell if the mouse is over it - NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; - NSRect closeRect = [currentCell closeButtonRectForFrame:cellFrame]; - [currentCell setHighlighted:NSMouseInRect(mousePoint, cellFrame, [self isFlipped])]; - [currentCell setCloseButtonOver:NSMouseInRect(mousePoint, closeRect, [self isFlipped])]; + + //highlight the cell if the mouse is over it + NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; + NSRect closeRect = [currentCell closeButtonRectForFrame:cellFrame]; + [currentCell setHighlighted:NSMouseInRect(mousePoint, cellFrame, [self isFlipped])]; + [currentCell setCloseButtonOver:NSMouseInRect(mousePoint, closeRect, [self isFlipped])]; } } - + //set the frame for the add tab button - if (_showAddTabButton) { - NSRect frame = [_addTabButton frame]; - frame.origin.x = [_controller addButtonRect].origin.x; - [_addTabButton setFrame:frame]; - } + if(_showAddTabButton) { + NSRect frame = [_addTabButton frame]; + frame.origin.x = [_controller addButtonRect].origin.x; + [_addTabButton setFrame:frame]; + } [_animationTimer invalidate]; [_animationTimer release]; _animationTimer = nil; - - for (NSInteger i = 0; i < cellCount; i++) { - currentCell = [_cells objectAtIndex:i]; - - //we've hit the cells that are in overflow, stop setting up tracking rects - if ([currentCell isInOverflowMenu]) { - break; - } - - [self _setupTrackingRectsForCell:currentCell]; - } - } - - [self setNeedsDisplay:YES]; -} - -- (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell -{ - NSInteger tag, index = [_cells indexOfObject:cell]; - NSRect cellTrackingRect = [_controller cellTrackingRectAtIndex:index]; - NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; - BOOL mouseInCell = NSMouseInRect(mousePoint, cellTrackingRect, [self isFlipped]); - - //set the cell tracking rect - [self removeTrackingRect:[cell cellTrackingTag]]; - tag = [self addTrackingRect:cellTrackingRect owner:cell userData:nil assumeInside:mouseInCell]; - [cell setCellTrackingTag:tag]; - [cell setHighlighted:mouseInCell]; - - if ([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { - NSRect closeRect = [_controller closeButtonTrackingRectAtIndex:index]; - BOOL mouseInCloseRect = NSMouseInRect(mousePoint, closeRect, [self isFlipped]); - - //set the close button tracking rect - [self removeTrackingRect:[cell closeButtonTrackingTag]]; - tag = [self addTrackingRect:closeRect owner:cell userData:nil assumeInside:mouseInCloseRect]; - [cell setCloseButtonTrackingTag:tag]; - - [cell setCloseButtonOver:mouseInCloseRect]; - } - - //set the tooltip tracking rect - [self addToolTipRect:[cell frame] owner:self userData:nil]; -} - -- (void)_positionOverflowMenu -{ - NSRect cellRect, frame = [self frame]; - cellRect.size.height = [style tabCellHeight]; - cellRect.size.width = [style rightMarginForTabBarControl]; - - if ([self orientation] == PSMTabBarHorizontalOrientation) { + + for(NSInteger i = 0; i < cellCount; i++) { + currentCell = [_cells objectAtIndex:i]; + + //we've hit the cells that are in overflow, stop setting up tracking rects + if([currentCell isInOverflowMenu]) { + break; + } + + [self _setupTrackingRectsForCell:currentCell]; + } + } + + [self setNeedsDisplay:YES]; +} + +- (void)_setupTrackingRectsForCell:(PSMTabBarCell *)cell { + NSInteger tag, index = [_cells indexOfObject:cell]; + NSRect cellTrackingRect = [_controller cellTrackingRectAtIndex:index]; + NSPoint mousePoint = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:nil]; + BOOL mouseInCell = NSMouseInRect(mousePoint, cellTrackingRect, [self isFlipped]); + + //set the cell tracking rect + [self removeTrackingRect:[cell cellTrackingTag]]; + tag = [self addTrackingRect:cellTrackingRect owner:cell userData:nil assumeInside:mouseInCell]; + [cell setCellTrackingTag:tag]; + [cell setHighlighted:mouseInCell]; + + if([cell hasCloseButton] && ![cell isCloseButtonSuppressed]) { + NSRect closeRect = [_controller closeButtonTrackingRectAtIndex:index]; + BOOL mouseInCloseRect = NSMouseInRect(mousePoint, closeRect, [self isFlipped]); + + //set the close button tracking rect + [self removeTrackingRect:[cell closeButtonTrackingTag]]; + tag = [self addTrackingRect:closeRect owner:cell userData:nil assumeInside:mouseInCloseRect]; + [cell setCloseButtonTrackingTag:tag]; + + [cell setCloseButtonOver:mouseInCloseRect]; + } + + //set the tooltip tracking rect + [self addToolTipRect:[cell frame] owner:self userData:nil]; +} + +- (void)_positionOverflowMenu { + NSRect cellRect, frame = [self frame]; + cellRect.size.height = [style tabCellHeight]; + cellRect.size.width = [style rightMarginForTabBarControl]; + + if([self orientation] == PSMTabBarHorizontalOrientation) { cellRect.origin.y = 0; cellRect.origin.x = frame.size.width - [style rightMarginForTabBarControl] + (_resizeAreaCompensation ? -(_resizeAreaCompensation - 1) : 1); [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin]; @@ -1176,28 +1122,27 @@ cellRect.size.width = frame.size.width; [_overflowPopUpButton setAutoresizingMask:NSViewNotSizable | NSViewMinXMargin | NSViewMinYMargin]; } - - [_overflowPopUpButton setFrame:cellRect]; + + [_overflowPopUpButton setFrame:cellRect]; } -- (void)_checkWindowFrame -{ +- (void)_checkWindowFrame { //figure out if the new frame puts the control in the way of the resize widget NSWindow *window = [self window]; - - if (window) { + + if(window) { NSRect resizeWidgetFrame = [[window contentView] frame]; resizeWidgetFrame.origin.x += resizeWidgetFrame.size.width - 22; resizeWidgetFrame.size.width = 22; resizeWidgetFrame.size.height = 22; - - if ([window showsResizeIndicator] && NSIntersectsRect([self frame], resizeWidgetFrame)) { + + if([window showsResizeIndicator] && NSIntersectsRect([self frame], resizeWidgetFrame)) { //the resize widgets are larger on metal windows _resizeAreaCompensation = [window styleMask] & NSTexturedBackgroundWindowMask ? 20 : 8; } else { _resizeAreaCompensation = 0; } - + [self _positionOverflowMenu]; } } @@ -1205,112 +1150,107 @@ #pragma mark - #pragma mark Mouse Tracking -- (BOOL)mouseDownCanMoveWindow -{ - return NO; +- (BOOL)mouseDownCanMoveWindow { + return NO; } -- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent -{ - return YES; +- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent { + return YES; } -- (void)mouseDown:(NSEvent *)theEvent -{ +- (void)mouseDown:(NSEvent *)theEvent { _didDrag = NO; - - // keep for dragging - [self setLastMouseDownEvent:theEvent]; - // what cell? - NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil]; + + // keep for dragging + [self setLastMouseDownEvent:theEvent]; + // what cell? + NSPoint mousePt = [self convertPoint:[theEvent locationInWindow] fromView:nil]; NSRect frame = [self frame]; - - if ([self orientation] == PSMTabBarVerticalOrientation && [self allowsResizing] && partnerView && (mousePt.x > frame.size.width - 3)) { + + if([self orientation] == PSMTabBarVerticalOrientation && [self allowsResizing] && partnerView && (mousePt.x > frame.size.width - 3)) { _resizing = YES; } - - NSRect cellFrame; - PSMTabBarCell *cell = [self cellForPoint:mousePt cellFrame:&cellFrame]; - if (cell) { + + NSRect cellFrame; + PSMTabBarCell *cell = [self cellForPoint:mousePt cellFrame:&cellFrame]; + if(cell) { BOOL overClose = NSMouseInRect(mousePt, [cell closeButtonRectForFrame:cellFrame], [self isFlipped]); - if (overClose && - ![self disableTabClose] && - ![cell isCloseButtonSuppressed] && - ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]] || [theEvent modifierFlags] & NSCommandKeyMask)) { - [cell setCloseButtonOver:NO]; - [cell setCloseButtonPressed:YES]; + if(overClose && + ![self disableTabClose] && + ![cell isCloseButtonSuppressed] && + ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]] || [theEvent modifierFlags] & NSCommandKeyMask)) { + [cell setCloseButtonOver:NO]; + [cell setCloseButtonPressed:YES]; _closeClicked = YES; - } else { - [cell setCloseButtonPressed:NO]; - if (_selectsTabsOnMouseDown) { + } else { + [cell setCloseButtonPressed:NO]; + if(_selectsTabsOnMouseDown) { [self performSelector:@selector(tabClick:) withObject:cell]; } - } - [self setNeedsDisplay:YES]; - } + } + [self setNeedsDisplay:YES]; + } } -- (void)mouseDragged:(NSEvent *)theEvent -{ - if ([self lastMouseDownEvent] == nil) { - return; - } - +- (void)mouseDragged:(NSEvent *)theEvent { + if([self lastMouseDownEvent] == nil) { + return; + } + NSPoint currentPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; - - if (_resizing) { + + if(_resizing) { NSRect frame = [self frame]; CGFloat resizeAmount = [theEvent deltaX]; - if ((currentPoint.x > frame.size.width && resizeAmount > 0) || (currentPoint.x < frame.size.width && resizeAmount < 0)) { + if((currentPoint.x > frame.size.width && resizeAmount > 0) || (currentPoint.x < frame.size.width && resizeAmount < 0)) { [[NSCursor resizeLeftRightCursor] push]; - + NSRect partnerFrame = [partnerView frame]; - + //do some bounds checking - if ((frame.size.width + resizeAmount > [self cellMinWidth]) && (frame.size.width + resizeAmount < [self cellMaxWidth])) { + if((frame.size.width + resizeAmount > [self cellMinWidth]) && (frame.size.width + resizeAmount < [self cellMaxWidth])) { frame.size.width += resizeAmount; partnerFrame.size.width -= resizeAmount; partnerFrame.origin.x += resizeAmount; - + [self setFrame:frame]; [partnerView setFrame:partnerFrame]; [[self superview] setNeedsDisplay:YES]; - } + } } return; } - - NSRect cellFrame; - NSPoint trackingStartPoint = [self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil]; - PSMTabBarCell *cell = [self cellForPoint:trackingStartPoint cellFrame:&cellFrame]; - if (cell) { + + NSRect cellFrame; + NSPoint trackingStartPoint = [self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil]; + PSMTabBarCell *cell = [self cellForPoint:trackingStartPoint cellFrame:&cellFrame]; + if(cell) { //check to see if the close button was the target in the clicked cell //highlight/unhighlight the close button as necessary NSRect iconRect = [cell closeButtonRectForFrame:cellFrame]; - - if (_closeClicked && NSMouseInRect(trackingStartPoint, iconRect, [self isFlipped]) && - ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]])) { + + if(_closeClicked && NSMouseInRect(trackingStartPoint, iconRect, [self isFlipped]) && + ([self allowsBackgroundTabClosing] || [[cell representedObject] isEqualTo:[tabView selectedTabViewItem]])) { [cell setCloseButtonPressed:NSMouseInRect(currentPoint, iconRect, [self isFlipped])]; [self setNeedsDisplay:YES]; return; } - + CGFloat dx = fabs(currentPoint.x - trackingStartPoint.x); CGFloat dy = fabs(currentPoint.y - trackingStartPoint.y); CGFloat distance = sqrt(dx * dx + dy * dy); - - if (distance >= 10 && !_didDrag && ![[PSMTabDragAssistant sharedDragAssistant] isDragging] && - [self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDragTabViewItem:fromTabBar:)] && - [[self delegate] tabView:tabView shouldDragTabViewItem:[cell representedObject] fromTabBar:self]) { + + if(distance >= 10 && !_didDrag && ![[PSMTabDragAssistant sharedDragAssistant] isDragging] && + [self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDragTabViewItem:fromTabBar:)] && + [[self delegate] tabView:tabView shouldDragTabViewItem:[cell representedObject] fromTabBar:self]) { _didDrag = YES; [[PSMTabDragAssistant sharedDragAssistant] startDraggingCell:cell fromTabBar:self withMouseDownEvent:[self lastMouseDownEvent]]; } } } -- (void)mouseUp:(NSEvent *)theEvent -{ - if (_resizing) { +- (void)mouseUp:(NSEvent *)theEvent { + if(_resizing) { _resizing = NO; [[NSCursor arrowCursor] set]; } else { @@ -1319,53 +1259,50 @@ NSRect cellFrame, mouseDownCellFrame; PSMTabBarCell *cell = [self cellForPoint:mousePt cellFrame:&cellFrame]; PSMTabBarCell *mouseDownCell = [self cellForPoint:[self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil] cellFrame:&mouseDownCellFrame]; - if (cell) { + if(cell) { NSPoint trackingStartPoint = [self convertPoint:[[self lastMouseDownEvent] locationInWindow] fromView:nil]; NSRect iconRect = [mouseDownCell closeButtonRectForFrame:mouseDownCellFrame]; - - if ((NSMouseInRect(mousePt, iconRect,[self isFlipped])) && ![self disableTabClose] && ![cell isCloseButtonSuppressed] && [mouseDownCell closeButtonPressed]) { - if (([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0) { + + if((NSMouseInRect(mousePt, iconRect, [self isFlipped])) && ![self disableTabClose] && ![cell isCloseButtonSuppressed] && [mouseDownCell closeButtonPressed]) { + if(([[NSApp currentEvent] modifierFlags] & NSAlternateKeyMask) != 0) { //If the user is holding Option, close all other tabs - NSEnumerator *enumerator = [[[[self cells] copy] autorelease] objectEnumerator]; - PSMTabBarCell *otherCell; - - while ((otherCell = [enumerator nextObject])) { - if (otherCell != cell) + NSEnumerator *enumerator = [[[[self cells] copy] autorelease] objectEnumerator]; + PSMTabBarCell *otherCell; + + while((otherCell = [enumerator nextObject])) { + if(otherCell != cell) { [self performSelector:@selector(closeTabClick:) withObject:otherCell]; + } } - + //Fix the close button for the clicked tab not to be pressed [cell setCloseButtonPressed:NO]; - } else { //Otherwise, close this tab [self performSelector:@selector(closeTabClick:) withObject:cell]; } - - } else if (NSMouseInRect(mousePt, mouseDownCellFrame, [self isFlipped]) && - (!NSMouseInRect(trackingStartPoint, [cell closeButtonRectForFrame:cellFrame], [self isFlipped]) || ![self allowsBackgroundTabClosing] || [self disableTabClose])) { + } else if(NSMouseInRect(mousePt, mouseDownCellFrame, [self isFlipped]) && + (!NSMouseInRect(trackingStartPoint, [cell closeButtonRectForFrame:cellFrame], [self isFlipped]) || ![self allowsBackgroundTabClosing] || [self disableTabClose])) { [mouseDownCell setCloseButtonPressed:NO]; // If -[self selectsTabsOnMouseDown] is TRUE, we already performed tabClick: on mouseDown. - if (![self selectsTabsOnMouseDown]) { + if(![self selectsTabsOnMouseDown]) { [self performSelector:@selector(tabClick:) withObject:cell]; } - } else { [mouseDownCell setCloseButtonPressed:NO]; [self performSelector:@selector(tabNothing:) withObject:cell]; } } - + _closeClicked = NO; } } -- (NSMenu *)menuForEvent:(NSEvent *)event -{ +- (NSMenu *)menuForEvent:(NSEvent *)event { NSMenu *menu = nil; NSTabViewItem *item = [[self cellForPoint:[self convertPoint:[event locationInWindow] fromView:nil] cellFrame:nil] representedObject]; - - if (item && [[self delegate] respondsToSelector:@selector(tabView:menuForTabViewItem:)]) { + + if(item && [[self delegate] respondsToSelector:@selector(tabView:menuForTabViewItem:)]) { menu = [[self delegate] tabView:tabView menuForTabViewItem:item]; } return menu; @@ -1374,146 +1311,129 @@ #pragma mark - #pragma mark Drag and Drop -- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent -{ - return YES; +- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent { + return YES; } // NSDraggingSource -- (NSUInteger)draggingSourceOperationMaskForLocal:(BOOL)isLocal -{ - return (isLocal ? NSDragOperationMove : NSDragOperationNone); +- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal { + return(isLocal ? NSDragOperationMove : NSDragOperationNone); } -- (BOOL)ignoreModifierKeysWhileDragging -{ - return YES; +- (BOOL)ignoreModifierKeysWhileDragging { + return YES; } -- (void)draggedImage:(NSImage *)anImage beganAt:(NSPoint)screenPoint -{ +- (void)draggedImage:(NSImage *)anImage beganAt:(NSPoint)screenPoint { [[PSMTabDragAssistant sharedDragAssistant] draggingBeganAt:screenPoint]; } -- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint -{ +- (void)draggedImage:(NSImage *)image movedTo:(NSPoint)screenPoint { [[PSMTabDragAssistant sharedDragAssistant] draggingMovedTo:screenPoint]; } // NSDraggingDestination -- (NSDragOperation)draggingEntered:(id )sender -{ - if([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { - - if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { +- (NSDragOperation)draggingEntered:(id )sender { + if([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { + if([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && + ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { return NSDragOperationNone; } - - [[PSMTabDragAssistant sharedDragAssistant] draggingEnteredTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; - return NSDragOperationMove; - } - - return NSDragOperationNone; + + [[PSMTabDragAssistant sharedDragAssistant] draggingEnteredTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; + return NSDragOperationMove; + } + + return NSDragOperationNone; } -- (NSDragOperation)draggingUpdated:(id )sender -{ +- (NSDragOperation)draggingUpdated:(id )sender { PSMTabBarCell *cell = [self cellForPoint:[self convertPoint:[sender draggingLocation] fromView:nil] cellFrame:nil]; - - if ([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { - - if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { + + if([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { + if([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && + ![[self delegate] tabView:[[sender draggingSource] tabView] shouldDropTabViewItem:[[[PSMTabDragAssistant sharedDragAssistant] draggedCell] representedObject] inTabBar:self]) { return NSDragOperationNone; } - - [[PSMTabDragAssistant sharedDragAssistant] draggingUpdatedInTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; - return NSDragOperationMove; - } else if (cell) { + + [[PSMTabDragAssistant sharedDragAssistant] draggingUpdatedInTabBar:self atPoint:[self convertPoint:[sender draggingLocation] fromView:nil]]; + return NSDragOperationMove; + } else if(cell) { //something that was accepted by the delegate was dragged on //Test for the space bar (the skip-the-delay key). - enum { virtualKeycodeForSpace = 49 }; //Source: IM:Tx (Fig. C-2) - union { - KeyMap keymap; - char bits[16]; - } keymap; - GetKeys(keymap.keymap); - if ((GetCurrentEventKeyModifiers() == 0) && bit_test(keymap.bits, virtualKeycodeForSpace)) { - //The user pressed the space bar. This skips the delay; the user wants to pop the spring on this tab *now*. - - //For some reason, it crashes if I call -fire here. I don't know why. It doesn't crash if I simply set the fire date to now. - [_springTimer setFireDate:[NSDate date]]; - } else { - //Wind the spring for a spring-loaded drop. - //The delay time comes from Finder's defaults, which specifies it in milliseconds. - //If the delegate can't handle our spring-loaded drop, we'll abort it when the timer fires. See fireSpring:. This is simpler than constantly (checking for spring-loaded awareness and tearing down/rebuilding the timer) at every delegate change. - - //If the user has dragged to a different tab, reset the timer. - if (_tabViewItemWithSpring != [cell representedObject]) { - [_springTimer invalidate]; - [_springTimer release]; _springTimer = nil; - _tabViewItemWithSpring = [cell representedObject]; - } - if (!_springTimer) { - //Finder's default delay time, as of Tiger, is 668 ms. If the user has never changed it, there's no setting in its defaults, so we default to that amount. - NSNumber *delayNumber = [(NSNumber *)CFPreferencesCopyAppValue((CFStringRef)@"SpringingDelayMilliseconds", (CFStringRef)@"com.apple.finder") autorelease]; - NSTimeInterval delaySeconds = delayNumber ? [delayNumber doubleValue] / 1000.0 : 0.668; - _springTimer = [[NSTimer scheduledTimerWithTimeInterval:delaySeconds - target:self - selector:@selector(fireSpring:) - userInfo:sender - repeats:NO] retain]; - } + /*enum { virtualKeycodeForSpace = 49 }; //Source: IM:Tx (Fig. C-2) + union { + KeyMap keymap; + char bits[16]; + } keymap; + GetKeys(keymap.keymap); + if ((GetCurrentEventKeyModifiers() == 0) && bit_test(keymap.bits, virtualKeycodeForSpace)) { + //The user pressed the space bar. This skips the delay; the user wants to pop the spring on this tab *now*. + + //For some reason, it crashes if I call -fire here. I don't know why. It doesn't crash if I simply set the fire date to now. + [_springTimer setFireDate:[NSDate date]]; + } else {*/ + //Wind the spring for a spring-loaded drop. + //The delay time comes from Finder's defaults, which specifies it in milliseconds. + //If the delegate can't handle our spring-loaded drop, we'll abort it when the timer fires. See fireSpring:. This is simpler than constantly (checking for spring-loaded awareness and tearing down/rebuilding the timer) at every delegate change. + + //If the user has dragged to a different tab, reset the timer. + if(_tabViewItemWithSpring != [cell representedObject]) { + [_springTimer invalidate]; + [_springTimer release]; _springTimer = nil; + _tabViewItemWithSpring = [cell representedObject]; + } + if(!_springTimer) { + //Finder's default delay time, as of Tiger, is 668 ms. If the user has never changed it, there's no setting in its defaults, so we default to that amount. + NSNumber *delayNumber = [(NSNumber *)CFPreferencesCopyAppValue((CFStringRef)@"SpringingDelayMilliseconds", (CFStringRef)@"com.apple.finder") autorelease]; + NSTimeInterval delaySeconds = delayNumber ?[delayNumber doubleValue] / 1000.0 : 0.668; + _springTimer = [[NSTimer scheduledTimerWithTimeInterval:delaySeconds + target:self + selector:@selector(fireSpring:) + userInfo:sender + repeats:NO] retain]; } return NSDragOperationCopy; } - - return NSDragOperationNone; + + return NSDragOperationNone; } -- (void)draggingExited:(id )sender -{ +- (void)draggingExited:(id )sender { [_springTimer invalidate]; [_springTimer release]; _springTimer = nil; - [[PSMTabDragAssistant sharedDragAssistant] draggingExitedTabBar:self]; + [[PSMTabDragAssistant sharedDragAssistant] draggingExitedTabBar:self]; } -- (BOOL)prepareForDragOperation:(id )sender -{ +- (BOOL)prepareForDragOperation:(id )sender { //validate the drag operation only if there's a valid tab bar to drop into return [[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] == NSNotFound || - [[PSMTabDragAssistant sharedDragAssistant] destinationTabBar] != nil; + [[PSMTabDragAssistant sharedDragAssistant] destinationTabBar] != nil; } -- (BOOL)performDragOperation:(id )sender -{ - if ([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { +- (BOOL)performDragOperation:(id )sender { + if([[[sender draggingPasteboard] types] indexOfObject:@"PSMTabBarControlItemPBType"] != NSNotFound) { [[PSMTabDragAssistant sharedDragAssistant] performDragOperation]; - } else if ([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:acceptedDraggingInfo:onTabViewItem:)]) { + } else if([self delegate] && [[self delegate] respondsToSelector:@selector(tabView:acceptedDraggingInfo:onTabViewItem:)]) { //forward the drop to the delegate [[self delegate] tabView:tabView acceptedDraggingInfo:sender onTabViewItem:[[self cellForPoint:[self convertPoint:[sender draggingLocation] fromView:nil] cellFrame:nil] representedObject]]; } - return YES; + return YES; } -- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ +- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation { [[PSMTabDragAssistant sharedDragAssistant] draggedImageEndedAt:aPoint operation:operation]; } -- (void)concludeDragOperation:(id )sender -{ - +- (void)concludeDragOperation:(id )sender { } #pragma mark - #pragma mark Spring-loading -- (void)fireSpring:(NSTimer *)timer -{ +- (void)fireSpring:(NSTimer *)timer { NSAssert1(timer == _springTimer, @"Spring fired by unrecognized timer %@", timer); id sender = [timer userInfo]; @@ -1528,116 +1448,106 @@ #pragma mark - #pragma mark Actions -- (void)overflowMenuAction:(id)sender -{ +- (void)overflowMenuAction:(id)sender { NSTabViewItem *tabViewItem = (NSTabViewItem *)[sender representedObject]; [tabView selectTabViewItem:tabViewItem]; } -- (void)closeTabClick:(id)sender -{ +- (void)closeTabClick:(id)sender { NSTabViewItem *item = [sender representedObject]; - [sender retain]; - if(([_cells count] == 1) && (![self canCloseOnlyTab])) - return; - - if ([[self delegate] respondsToSelector:@selector(tabView:shouldCloseTabViewItem:)]) { - if (![[self delegate] tabView:tabView shouldCloseTabViewItem:item]) { - // fix mouse downed close button - [sender setCloseButtonPressed:NO]; - return; - } - } - - [item retain]; - + [sender retain]; + if(([_cells count] == 1) && (![self canCloseOnlyTab])) { + return; + } + + if([[self delegate] respondsToSelector:@selector(tabView:shouldCloseTabViewItem:)]) { + if(![[self delegate] tabView:tabView shouldCloseTabViewItem:item]) { + // fix mouse downed close button + [sender setCloseButtonPressed:NO]; + return; + } + } + + [item retain]; + [tabView removeTabViewItem:item]; - [item release]; - [sender release]; + [item release]; + [sender release]; } -- (void)tabClick:(id)sender -{ - [tabView selectTabViewItem:[sender representedObject]]; +- (void)tabClick:(id)sender { + [tabView selectTabViewItem:[sender representedObject]]; } -- (void)tabNothing:(id)sender -{ - //[self update]; // takes care of highlighting based on state +- (void)tabNothing:(id)sender { + //[self update]; // takes care of highlighting based on state } -- (void)frameDidChange:(NSNotification *)notification -{ +- (void)frameDidChange:(NSNotification *)notification { [self _checkWindowFrame]; // trying to address the drawing artifacts for the progress indicators - hackery follows // this one fixes the "blanking" effect when the control hides and shows itself NSEnumerator *e = [_cells objectEnumerator]; PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { + while((cell = [e nextObject])) { [[cell indicator] stopAnimation:self]; [[cell indicator] performSelector:@selector(startAnimation:) - withObject:nil - afterDelay:0]; + withObject:nil + afterDelay:0]; } [self update:NO]; } -- (void)viewDidMoveToWindow -{ +- (void)viewDidMoveToWindow { [self _checkWindowFrame]; } -- (void)viewWillStartLiveResize -{ - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - [[cell indicator] stopAnimation:self]; - } - [self setNeedsDisplay:YES]; +- (void)viewWillStartLiveResize { + NSEnumerator *e = [_cells objectEnumerator]; + PSMTabBarCell *cell; + while((cell = [e nextObject])) { + [[cell indicator] stopAnimation:self]; + } + [self setNeedsDisplay:YES]; } --(void)viewDidEndLiveResize -{ - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { - [[cell indicator] startAnimation:self]; - } - +-(void)viewDidEndLiveResize { + NSEnumerator *e = [_cells objectEnumerator]; + PSMTabBarCell *cell; + while((cell = [e nextObject])) { + [[cell indicator] startAnimation:self]; + } + [self _checkWindowFrame]; - [self update:NO]; + [self update:NO]; } -- (void)resetCursorRects -{ +- (void)resetCursorRects { [super resetCursorRects]; - if ([self orientation] == PSMTabBarVerticalOrientation) { + if([self orientation] == PSMTabBarVerticalOrientation) { NSRect frame = [self frame]; [self addCursorRect:NSMakeRect(frame.size.width - 2, 0, 2, frame.size.height) cursor:[NSCursor resizeLeftRightCursor]]; } } -- (void)windowDidMove:(NSNotification *)aNotification -{ - [self setNeedsDisplay:YES]; +- (void)windowDidMove:(NSNotification *)aNotification { + [self setNeedsDisplay:YES]; } -- (void)windowDidUpdate:(NSNotification *)notification -{ - // hide? must readjust things if I'm not supposed to be showing - // this block of code only runs when the app launches - if ([self hideForSingleTab] && ([_cells count] <= 1) && !_awakenedFromNib) { - // must adjust frames now before display - NSRect myFrame = [self frame]; - if ([self orientation] == PSMTabBarHorizontalOrientation) { - if (partnerView) { +- (void)windowDidUpdate:(NSNotification *)notification { + // hide? must readjust things if I'm not supposed to be showing + // this block of code only runs when the app launches + if([self hideForSingleTab] && ([_cells count] <= 1) && !_awakenedFromNib) { + // must adjust frames now before display + NSRect myFrame = [self frame]; + if([self orientation] == PSMTabBarHorizontalOrientation) { + if(partnerView) { NSRect partnerFrame = [partnerView frame]; // above or below me? - if (myFrame.origin.y - 22 > [partnerView frame].origin.y) { + if(myFrame.origin.y - 22 > [partnerView frame].origin.y) { // partner is below me [self setFrame:NSMakeRect(myFrame.origin.x, myFrame.origin.y + 21, myFrame.size.width, myFrame.size.height - 21)]; [partnerView setFrame:NSMakeRect(partnerFrame.origin.x, partnerFrame.origin.y, partnerFrame.size.width, partnerFrame.size.height + 21)]; @@ -1655,10 +1565,10 @@ [self setFrame:NSMakeRect(myFrame.origin.x, myFrame.origin.y, myFrame.size.width, myFrame.size.height - 21)]; } } else { - if (partnerView) { + if(partnerView) { NSRect partnerFrame = [partnerView frame]; //to the left or right? - if (myFrame.origin.x < [partnerView frame].origin.x) { + if(myFrame.origin.x < [partnerView frame].origin.x) { // partner is to the left [self setFrame:NSMakeRect(myFrame.origin.x, myFrame.origin.y, 1, myFrame.size.height)]; [partnerView setFrame:NSMakeRect(partnerFrame.origin.x - myFrame.size.width + 1, partnerFrame.origin.y, partnerFrame.size.width + myFrame.size.width - 1, partnerFrame.size.height)]; @@ -1677,17 +1587,17 @@ [self setFrame:NSMakeRect(myFrame.origin.x, myFrame.origin.y, 1, myFrame.size.height)]; } } - - _isHidden = YES; - - if ([[self delegate] respondsToSelector:@selector(tabView:tabBarDidHide:)]) { + + _isHidden = YES; + + if([[self delegate] respondsToSelector:@selector(tabView:tabBarDidHide:)]) { [[self delegate] tabView:[self tabView] tabBarDidHide:self]; } - } - + } + _awakenedFromNib = YES; [self setNeedsDisplay:YES]; - + //we only need to do this once [[NSNotificationCenter defaultCenter] removeObserver:self name:NSWindowDidUpdateNotification object:nil]; } @@ -1695,31 +1605,28 @@ #pragma mark - #pragma mark Menu Validation -- (BOOL)validateMenuItem:(NSMenuItem *)sender -{ +- (BOOL)validateMenuItem:(NSMenuItem *)sender { [sender setState:([[sender representedObject] isEqualTo:[tabView selectedTabViewItem]]) ? NSOnState : NSOffState]; - + return [[self delegate] respondsToSelector:@selector(tabView:validateOverflowMenuItem:forTabViewItem:)] ? - [[self delegate] tabView:[self tabView] validateOverflowMenuItem:sender forTabViewItem:[sender representedObject]] : YES; + [[self delegate] tabView:[self tabView] validateOverflowMenuItem:sender forTabViewItem:[sender representedObject]] : YES; } #pragma mark - #pragma mark NSTabView Delegate -- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - // here's a weird one - this message is sent before the "tabViewDidChangeNumberOfTabViewItems" - // message, thus I can end up updating when there are no cells, if no tabs were (yet) present +- (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem { + // here's a weird one - this message is sent before the "tabViewDidChangeNumberOfTabViewItems" + // message, thus I can end up updating when there are no cells, if no tabs were (yet) present NSInteger tabIndex = [aTabView indexOfTabViewItem:tabViewItem]; - - if ([_cells count] > 0 && tabIndex < [_cells count]) { + + if([_cells count] > 0 && tabIndex < [_cells count]) { PSMTabBarCell *thisCell = [_cells objectAtIndex:tabIndex]; - if (_alwaysShowActiveTab && [thisCell isInOverflowMenu]) { - + if(_alwaysShowActiveTab && [thisCell isInOverflowMenu]) { //temporarily disable the delegate in order to move the tab to a different index id tempDelegate = [aTabView delegate]; [aTabView setDelegate:nil]; - + // move it all around first [tabViewItem retain]; [thisCell retain]; @@ -1727,85 +1634,83 @@ [aTabView insertTabViewItem:tabViewItem atIndex:0]; [_cells removeObjectAtIndex:tabIndex]; [_cells insertObject:thisCell atIndex:0]; - [thisCell setIsInOverflowMenu:NO]; //very important else we get a fun recursive loop going - [[_cells objectAtIndex:[_cells count] - 1] setIsInOverflowMenu:YES]; //these 2 lines are pretty uncool and this logic needs to be updated + [thisCell setIsInOverflowMenu:NO]; //very important else we get a fun recursive loop going + [[_cells objectAtIndex:[_cells count] - 1] setIsInOverflowMenu:YES]; //these 2 lines are pretty uncool and this logic needs to be updated [thisCell release]; [tabViewItem release]; - + [aTabView setDelegate:tempDelegate]; - - //reset the selection since removing it changed the selection + + //reset the selection since removing it changed the selection [aTabView selectTabViewItem:tabViewItem]; - + [self update]; } else { - [_controller setSelectedCell:thisCell]; - [self setNeedsDisplay:YES]; + [_controller setSelectedCell:thisCell]; + [self setNeedsDisplay:YES]; } - } - - if ([[self delegate] respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) { + } + + if([[self delegate] respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) { [[self delegate] performSelector:@selector(tabView:didSelectTabViewItem:) withObject:aTabView withObject:tabViewItem]; } } -- (BOOL)tabView:(NSTabView *)aTabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[self delegate] respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) { +- (BOOL)tabView:(NSTabView *)aTabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem { + if([[self delegate] respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) { return [[self delegate] tabView:aTabView shouldSelectTabViewItem:tabViewItem]; } else { return YES; } } -- (void)tabView:(NSTabView *)aTabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem -{ - if ([[self delegate] respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) { +- (void)tabView:(NSTabView *)aTabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem { + if([[self delegate] respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) { [[self delegate] performSelector:@selector(tabView:willSelectTabViewItem:) withObject:aTabView withObject:tabViewItem]; } } -- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView -{ - NSArray *tabItems = [tabView tabViewItems]; - // go through cells, remove any whose representedObjects are not in [tabView tabViewItems] - NSEnumerator *e = [[[_cells copy] autorelease] objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject]) ) { +- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView { + NSArray *tabItems = [tabView tabViewItems]; + // go through cells, remove any whose representedObjects are not in [tabView tabViewItems] + NSEnumerator *e = [[[_cells copy] autorelease] objectEnumerator]; + PSMTabBarCell *cell; + while((cell = [e nextObject])) { //remove the observer binding - if ([cell representedObject] && ![tabItems containsObject:[cell representedObject]]) { - if ([[self delegate] respondsToSelector:@selector(tabView:didCloseTabViewItem:)]) { + if([cell representedObject] && ![tabItems containsObject:[cell representedObject]]) { + if([[self delegate] respondsToSelector:@selector(tabView:didCloseTabViewItem:)]) { [[self delegate] tabView:aTabView didCloseTabViewItem:[cell representedObject]]; } - - [self removeTabForCell:cell]; - } - } - - // go through tab view items, add cell for any not present - NSMutableArray *cellItems = [self representedTabViewItems]; - NSEnumerator *ex = [tabItems objectEnumerator]; - NSTabViewItem *item; - while ( (item = [ex nextObject]) ) { - if (![cellItems containsObject:item]) { - [self addTabViewItem:item]; - } - } - - // pass along for other delegate responses - if ([[self delegate] respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)]) { - [[self delegate] performSelector:@selector(tabViewDidChangeNumberOfTabViewItems:) withObject:aTabView]; - } - + + [self removeTabForCell:cell]; + } + } + + // go through tab view items, add cell for any not present + NSMutableArray *cellItems = [self representedTabViewItems]; + NSEnumerator *ex = [tabItems objectEnumerator]; + NSTabViewItem *item; + while((item = [ex nextObject])) { + if(![cellItems containsObject:item]) { + [self addTabViewItem:item]; + } + } + + // pass along for other delegate responses + if([[self delegate] respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)]) { + [[self delegate] performSelector:@selector(tabViewDidChangeNumberOfTabViewItems:) withObject:aTabView]; + } + // reset cursor tracking for the add tab button if one exists - if ([self addTabButton]) [[self addTabButton] resetCursorRects]; + if([self addTabButton]) { + [[self addTabButton] resetCursorRects]; + } } #pragma mark - #pragma mark Tooltips -- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData -{ - if ([[self delegate] respondsToSelector:@selector(tabView:toolTipForTabViewItem:)]) { +- (NSString *)view:(NSView *)view stringForToolTip:(NSToolTipTag)tag point:(NSPoint)point userData:(void *)userData { + if([[self delegate] respondsToSelector:@selector(tabView:toolTipForTabViewItem:)]) { return [[self delegate] tabView:[self tabView] toolTipForTabViewItem:[[self cellForPoint:point cellFrame:nil] representedObject]]; } return nil; @@ -1816,232 +1721,231 @@ - (void)encodeWithCoder:(NSCoder *)aCoder { - [super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_cells forKey:@"PSMcells"]; - [aCoder encodeObject:tabView forKey:@"PSMtabView"]; - [aCoder encodeObject:_overflowPopUpButton forKey:@"PSMoverflowPopUpButton"]; - [aCoder encodeObject:_addTabButton forKey:@"PSMaddTabButton"]; - [aCoder encodeObject:style forKey:@"PSMstyle"]; + [super encodeWithCoder:aCoder]; + if ([aCoder allowsKeyedCoding]) { + [aCoder encodeObject:_cells forKey:@"PSMcells"]; + [aCoder encodeObject:tabView forKey:@"PSMtabView"]; + [aCoder encodeObject:_overflowPopUpButton forKey:@"PSMoverflowPopUpButton"]; + [aCoder encodeObject:_addTabButton forKey:@"PSMaddTabButton"]; + [aCoder encodeObject:style forKey:@"PSMstyle"]; [aCoder encodeInteger:_orientation forKey:@"PSMorientation"]; - [aCoder encodeBool:_canCloseOnlyTab forKey:@"PSMcanCloseOnlyTab"]; + [aCoder encodeBool:_canCloseOnlyTab forKey:@"PSMcanCloseOnlyTab"]; [aCoder encodeBool:_disableTabClose forKey:@"PSMdisableTabClose"]; - [aCoder encodeBool:_hideForSingleTab forKey:@"PSMhideForSingleTab"]; + [aCoder encodeBool:_hideForSingleTab forKey:@"PSMhideForSingleTab"]; [aCoder encodeBool:_allowsBackgroundTabClosing forKey:@"PSMallowsBackgroundTabClosing"]; [aCoder encodeBool:_allowsResizing forKey:@"PSMallowsResizing"]; [aCoder encodeBool:_selectsTabsOnMouseDown forKey:@"PSMselectsTabsOnMouseDown"]; - [aCoder encodeBool:_showAddTabButton forKey:@"PSMshowAddTabButton"]; - [aCoder encodeBool:_sizeCellsToFit forKey:@"PSMsizeCellsToFit"]; - [aCoder encodeInteger:_cellMinWidth forKey:@"PSMcellMinWidth"]; - [aCoder encodeInteger:_cellMaxWidth forKey:@"PSMcellMaxWidth"]; - [aCoder encodeInteger:_cellOptimumWidth forKey:@"PSMcellOptimumWidth"]; - [aCoder encodeInteger:_currentStep forKey:@"PSMcurrentStep"]; - [aCoder encodeBool:_isHidden forKey:@"PSMisHidden"]; - [aCoder encodeObject:partnerView forKey:@"PSMpartnerView"]; - [aCoder encodeBool:_awakenedFromNib forKey:@"PSMawakenedFromNib"]; - [aCoder encodeObject:_lastMouseDownEvent forKey:@"PSMlastMouseDownEvent"]; - [aCoder encodeObject:delegate forKey:@"PSMdelegate"]; + [aCoder encodeBool:_showAddTabButton forKey:@"PSMshowAddTabButton"]; + [aCoder encodeBool:_sizeCellsToFit forKey:@"PSMsizeCellsToFit"]; + [aCoder encodeInteger:_cellMinWidth forKey:@"PSMcellMinWidth"]; + [aCoder encodeInteger:_cellMaxWidth forKey:@"PSMcellMaxWidth"]; + [aCoder encodeInteger:_cellOptimumWidth forKey:@"PSMcellOptimumWidth"]; + [aCoder encodeInteger:_currentStep forKey:@"PSMcurrentStep"]; + [aCoder encodeBool:_isHidden forKey:@"PSMisHidden"]; + [aCoder encodeObject:partnerView forKey:@"PSMpartnerView"]; + [aCoder encodeBool:_awakenedFromNib forKey:@"PSMawakenedFromNib"]; + [aCoder encodeObject:_lastMouseDownEvent forKey:@"PSMlastMouseDownEvent"]; + [aCoder encodeObject:delegate forKey:@"PSMdelegate"]; [aCoder encodeBool:_useOverflowMenu forKey:@"PSMuseOverflowMenu"]; [aCoder encodeBool:_automaticallyAnimates forKey:@"PSMautomaticallyAnimates"]; [aCoder encodeBool:_alwaysShowActiveTab forKey:@"PSMalwaysShowActiveTab"]; - } + } } - (id)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if (self) { - if ([aDecoder allowsKeyedCoding]) { - _cells = [[aDecoder decodeObjectForKey:@"PSMcells"] retain]; - tabView = [[aDecoder decodeObjectForKey:@"PSMtabView"] retain]; - _overflowPopUpButton = [[aDecoder decodeObjectForKey:@"PSMoverflowPopUpButton"] retain]; - _addTabButton = [[aDecoder decodeObjectForKey:@"PSMaddTabButton"] retain]; - style = [[aDecoder decodeObjectForKey:@"PSMstyle"] retain]; + self = [super initWithCoder:aDecoder]; + if (self) { + // Initialization + [self initAddedProperties]; + [self registerForDraggedTypes:[NSArray arrayWithObjects:@"PSMTabBarControlItemPBType", nil]]; + + // resize + [self setPostsFrameChangedNotifications:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(frameDidChange:) name:NSViewFrameDidChangeNotification object:self]; + if ([aDecoder allowsKeyedCoding]) { + _cells = [[aDecoder decodeObjectForKey:@"PSMcells"] retain]; + tabView = [[aDecoder decodeObjectForKey:@"PSMtabView"] retain]; + _overflowPopUpButton = [[aDecoder decodeObjectForKey:@"PSMoverflowPopUpButton"] retain]; + _addTabButton = [[aDecoder decodeObjectForKey:@"PSMaddTabButton"] retain]; + style = [[aDecoder decodeObjectForKey:@"PSMstyle"] retain]; _orientation = (PSMTabBarOrientation)[aDecoder decodeIntegerForKey:@"PSMorientation"]; - _canCloseOnlyTab = [aDecoder decodeBoolForKey:@"PSMcanCloseOnlyTab"]; + _canCloseOnlyTab = [aDecoder decodeBoolForKey:@"PSMcanCloseOnlyTab"]; _disableTabClose = [aDecoder decodeBoolForKey:@"PSMdisableTabClose"]; - _hideForSingleTab = [aDecoder decodeBoolForKey:@"PSMhideForSingleTab"]; + _hideForSingleTab = [aDecoder decodeBoolForKey:@"PSMhideForSingleTab"]; _allowsBackgroundTabClosing = [aDecoder decodeBoolForKey:@"PSMallowsBackgroundTabClosing"]; _allowsResizing = [aDecoder decodeBoolForKey:@"PSMallowsResizing"]; _selectsTabsOnMouseDown = [aDecoder decodeBoolForKey:@"PSMselectsTabsOnMouseDown"]; - _showAddTabButton = [aDecoder decodeBoolForKey:@"PSMshowAddTabButton"]; - _sizeCellsToFit = [aDecoder decodeBoolForKey:@"PSMsizeCellsToFit"]; - _cellMinWidth = [aDecoder decodeIntegerForKey:@"PSMcellMinWidth"]; - _cellMaxWidth = [aDecoder decodeIntegerForKey:@"PSMcellMaxWidth"]; - _cellOptimumWidth = [aDecoder decodeIntegerForKey:@"PSMcellOptimumWidth"]; - _currentStep = [aDecoder decodeIntegerForKey:@"PSMcurrentStep"]; - _isHidden = [aDecoder decodeBoolForKey:@"PSMisHidden"]; - partnerView = [[aDecoder decodeObjectForKey:@"PSMpartnerView"] retain]; - _awakenedFromNib = [aDecoder decodeBoolForKey:@"PSMawakenedFromNib"]; - _lastMouseDownEvent = [[aDecoder decodeObjectForKey:@"PSMlastMouseDownEvent"] retain]; + _showAddTabButton = [aDecoder decodeBoolForKey:@"PSMshowAddTabButton"]; + _sizeCellsToFit = [aDecoder decodeBoolForKey:@"PSMsizeCellsToFit"]; + _cellMinWidth = [aDecoder decodeIntegerForKey:@"PSMcellMinWidth"]; + _cellMaxWidth = [aDecoder decodeIntegerForKey:@"PSMcellMaxWidth"]; + _cellOptimumWidth = [aDecoder decodeIntegerForKey:@"PSMcellOptimumWidth"]; + _currentStep = [aDecoder decodeIntegerForKey:@"PSMcurrentStep"]; + _isHidden = [aDecoder decodeBoolForKey:@"PSMisHidden"]; + partnerView = [[aDecoder decodeObjectForKey:@"PSMpartnerView"] retain]; + _awakenedFromNib = [aDecoder decodeBoolForKey:@"PSMawakenedFromNib"]; + _lastMouseDownEvent = [[aDecoder decodeObjectForKey:@"PSMlastMouseDownEvent"] retain]; _useOverflowMenu = [aDecoder decodeBoolForKey:@"PSMuseOverflowMenu"]; _automaticallyAnimates = [aDecoder decodeBoolForKey:@"PSMautomaticallyAnimates"]; _alwaysShowActiveTab = [aDecoder decodeBoolForKey:@"PSMalwaysShowActiveTab"]; - delegate = [[aDecoder decodeObjectForKey:@"PSMdelegate"] retain]; - } - } - return self; + delegate = [[aDecoder decodeObjectForKey:@"PSMdelegate"] retain]; + } + } + [self setTarget:self]; + return self; } #pragma mark - #pragma mark IB Palette -- (NSSize)minimumFrameSizeFromKnobPosition:(NSInteger)position -{ - return NSMakeSize(100.0, 22.0); +- (NSSize)minimumFrameSizeFromKnobPosition:(NSInteger)position { + return NSMakeSize(100.0, 22.0); } -- (NSSize)maximumFrameSizeFromKnobPosition:(NSInteger)knobPosition -{ - return NSMakeSize(10000.0, 22.0); +- (NSSize)maximumFrameSizeFromKnobPosition:(NSInteger)knobPosition { + return NSMakeSize(10000.0, 22.0); } -- (void)placeView:(NSRect)newFrame -{ - // this is called any time the view is resized in IB - [self setFrame:newFrame]; - [self update:NO]; +- (void)placeView:(NSRect)newFrame { + // this is called any time the view is resized in IB + [self setFrame:newFrame]; + [self update:NO]; } #pragma mark - #pragma mark Convenience -- (void)bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item -{ - [self _bindPropertiesForCell:cell andTabViewItem:item]; - - // watch for changes in the identifier - [item addObserver:self forKeyPath:@"identifier" options:0 context:nil]; +- (void)bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item { + [self _bindPropertiesForCell:cell andTabViewItem:item]; + + // watch for changes in the identifier + [item addObserver:self forKeyPath:@"identifier" options:0 context:nil]; } -- (void)_bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item -{ - // bind the indicator to the represented object's status (if it exists) - [[cell indicator] setHidden:YES]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(isProcessing)]) { +- (void)_bindPropertiesForCell:(PSMTabBarCell *)cell andTabViewItem:(NSTabViewItem *)item { + // bind the indicator to the represented object's status (if it exists) + [[cell indicator] setHidden:YES]; + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(isProcessing)]) { NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; [bindingOptions setObject:NSNegateBooleanTransformerName forKey:@"NSValueTransformerName"]; [[cell indicator] bind:@"animate" toObject:[item identifier] withKeyPath:@"isProcessing" options:nil]; [[cell indicator] bind:@"hidden" toObject:[item identifier] withKeyPath:@"isProcessing" options:bindingOptions]; - [[item identifier] addObserver:cell forKeyPath:@"isProcessing" options:0 context:nil]; - } - } - - // bind for the existence of an icon - [cell setHasIcon:NO]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(icon)]) { + [[item identifier] addObserver:cell forKeyPath:@"isProcessing" options:0 context:nil]; + } + } + + // bind for the existence of an icon + [cell setHasIcon:NO]; + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(icon)]) { NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; [bindingOptions setObject:NSIsNotNilTransformerName forKey:@"NSValueTransformerName"]; [cell bind:@"hasIcon" toObject:[item identifier] withKeyPath:@"icon" options:bindingOptions]; [[item identifier] addObserver:cell forKeyPath:@"icon" options:0 context:nil]; - } - } - - // bind for the existence of a counter - [cell setCount:0]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(objectCount)]) { + } + } + + // bind for the existence of a counter + [cell setCount:0]; + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(objectCount)]) { [cell bind:@"count" toObject:[item identifier] withKeyPath:@"objectCount" options:nil]; [[item identifier] addObserver:cell forKeyPath:@"objectCount" options:0 context:nil]; } - } - - // bind for the color of a counter - [cell setCountColor:nil]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(countColor)]) { + } + + // bind for the color of a counter + [cell setCountColor:nil]; + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(countColor)]) { [cell bind:@"countColor" toObject:[item identifier] withKeyPath:@"countColor" options:nil]; [[item identifier] addObserver:cell forKeyPath:@"countColor" options:0 context:nil]; } - } + } // bind for a large image [cell setHasLargeImage:NO]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(largeImage)]) { + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(largeImage)]) { NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionary]; [bindingOptions setObject:NSIsNotNilTransformerName forKey:@"NSValueTransformerName"]; [cell bind:@"hasLargeImage" toObject:[item identifier] withKeyPath:@"largeImage" options:bindingOptions]; [[item identifier] addObserver:cell forKeyPath:@"largeImage" options:0 context:nil]; } - } - - [cell setIsEdited:NO]; - if ([item identifier] != nil) { - if ([[[cell representedObject] identifier] respondsToSelector:@selector(isEdited)]) { + } + + [cell setIsEdited:NO]; + if([item identifier] != nil) { + if([[[cell representedObject] identifier] respondsToSelector:@selector(isEdited)]) { [cell bind:@"isEdited" toObject:[item identifier] withKeyPath:@"isEdited" options:nil]; [[item identifier] addObserver:cell forKeyPath:@"isEdited" options:0 context:nil]; } - } - - // bind my string value to the label on the represented tab - [cell bind:@"title" toObject:item withKeyPath:@"label" options:nil]; + } + + // bind my string value to the label on the represented tab + [cell bind:@"title" toObject:item withKeyPath:@"label" options:nil]; } -- (NSMutableArray *)representedTabViewItems -{ - NSMutableArray *temp = [NSMutableArray arrayWithCapacity:[_cells count]]; - NSEnumerator *e = [_cells objectEnumerator]; - PSMTabBarCell *cell; - while ( (cell = [e nextObject])) { - if ([cell representedObject]) { +- (NSMutableArray *)representedTabViewItems { + NSMutableArray *temp = [NSMutableArray arrayWithCapacity:[_cells count]]; + NSEnumerator *e = [_cells objectEnumerator]; + PSMTabBarCell *cell; + while((cell = [e nextObject])) { + if([cell representedObject]) { [temp addObject:[cell representedObject]]; } - } - return temp; + } + return temp; } -- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame -{ - if ([self orientation] == PSMTabBarHorizontalOrientation && !NSPointInRect(point, [self genericCellRect])) { - return nil; - } - - NSInteger i, cnt = [_cells count]; - for (i = 0; i < cnt; i++) { - PSMTabBarCell *cell = [_cells objectAtIndex:i]; - - if (NSPointInRect(point, [cell frame])) { - if (outFrame) { - *outFrame = [cell frame]; - } - return cell; - } - } - return nil; -} - -- (PSMTabBarCell *)lastVisibleTab -{ - NSInteger i, cellCount = [_cells count]; - for (i = 0; i < cellCount; i++) { - if ([[_cells objectAtIndex:i] isInOverflowMenu]) { - return [_cells objectAtIndex:(i - 1)]; - } - } - return [_cells objectAtIndex:(cellCount - 1)]; +- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame { + if([self orientation] == PSMTabBarHorizontalOrientation && !NSPointInRect(point, [self genericCellRect])) { + return nil; + } + + NSInteger i, cnt = [_cells count]; + for(i = 0; i < cnt; i++) { + PSMTabBarCell *cell = [_cells objectAtIndex:i]; + + if(NSPointInRect(point, [cell frame])) { + if(outFrame) { + *outFrame = [cell frame]; + } + return cell; + } + } + return nil; } -- (NSInteger)numberOfVisibleTabs -{ - NSInteger cellCount = 0; +- (PSMTabBarCell *)lastVisibleTab { + NSInteger i, cellCount = [_cells count]; + for(i = 0; i < cellCount; i++) { + if([[_cells objectAtIndex:i] isInOverflowMenu]) { + return [_cells objectAtIndex:(i - 1)]; + } + } + return [_cells objectAtIndex:(cellCount - 1)]; +} + +- (NSInteger)numberOfVisibleTabs { + NSInteger i, cellCount = 0; PSMTabBarCell *nextCell; - - for (NSUInteger i = 0; i < [_cells count]; i++) { + + for(i = 0; i < [_cells count]; i++) { nextCell = [_cells objectAtIndex:i]; - - if ([nextCell isInOverflowMenu]) { - break; - } - - if (![nextCell isPlaceholder]) { + + if([nextCell isInOverflowMenu]) { + break; + } + + if(![nextCell isPlaceholder]) { cellCount++; } - } - - return cellCount; + } + + return cellCount; } #pragma mark - @@ -2053,9 +1957,9 @@ - (id)accessibilityAttributeValue:(NSString *)attribute { id attributeValue = nil; - if ([attribute isEqualToString: NSAccessibilityRoleAttribute]) { + if([attribute isEqualToString: NSAccessibilityRoleAttribute]) { attributeValue = NSAccessibilityGroupRole; - } else if ([attribute isEqualToString: NSAccessibilityChildrenAttribute]) { + } else if([attribute isEqualToString: NSAccessibilityChildrenAttribute]) { attributeValue = NSAccessibilityUnignoredChildren(_cells); } else { attributeValue = [super accessibilityAttributeValue:attribute]; @@ -2065,21 +1969,21 @@ - (id)accessibilityHitTest:(NSPoint)point { id hitTestResult = self; - + NSEnumerator *enumerator = [_cells objectEnumerator]; PSMTabBarCell *cell = nil; PSMTabBarCell *highlightedCell = nil; - - while (!highlightedCell && (cell = [enumerator nextObject])) { - if ([cell isHighlighted]) { + + while(!highlightedCell && (cell = [enumerator nextObject])) { + if([cell isHighlighted]) { highlightedCell = cell; } } - - if (highlightedCell) { + + if(highlightedCell) { hitTestResult = [highlightedCell accessibilityHitTest:point]; } - + return hitTestResult; } diff --git a/cocoa/PSMTabBarControl/PSMTabBarController.h b/cocoa/PSMTabBarControl/PSMTabBarController.h index c675b981e..447011f44 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarController.h +++ b/cocoa/PSMTabBarControl/PSMTabBarController.h @@ -10,12 +10,17 @@ @class PSMTabBarControl, PSMTabBarCell; -@interface PSMTabBarController : NSObject { - PSMTabBarControl *_control; - NSMutableArray *_cellTrackingRects, *_closeButtonTrackingRects; - NSMutableArray *_cellFrames; - NSRect _addButtonRect; - NSMenu *_overflowMenu; +@interface PSMTabBarController : NSObject +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 + +#endif +{ + PSMTabBarControl *_control; + NSMutableArray *_cellTrackingRects; + NSMutableArray *_closeButtonTrackingRects; + NSMutableArray *_cellFrames; + NSRect _addButtonRect; + NSMenu *_overflowMenu; } - (id)initWithTabBarControl:(PSMTabBarControl *)control; diff --git a/cocoa/PSMTabBarControl/PSMTabBarController.m b/cocoa/PSMTabBarControl/PSMTabBarController.m index 69542c865..7d9820e61 100644 --- a/cocoa/PSMTabBarControl/PSMTabBarController.m +++ b/cocoa/PSMTabBarControl/PSMTabBarController.m @@ -12,7 +12,7 @@ #import "PSMTabStyle.h" #import "NSString_AITruncation.h" -#define MAX_OVERFLOW_MENUITEM_TITLE_LENGTH 60 +#define MAX_OVERFLOW_MENUITEM_TITLE_LENGTH 60 @interface PSMTabBarController (Private) - (NSArray *)_generateWidthsFromCells:(NSArray *)cells; @@ -28,26 +28,24 @@ PSMTabBarControl. @param A PSMTabBarControl. @returns A newly created PSMTabBarController instance. -*/ - -- (id)initWithTabBarControl:(PSMTabBarControl *)control -{ - if ( (self = [super init]) ) { - _control = control; - _cellTrackingRects = [[NSMutableArray alloc] init]; - _closeButtonTrackingRects = [[NSMutableArray alloc] init]; - _cellFrames = [[NSMutableArray alloc] init]; + */ + +- (id)initWithTabBarControl:(PSMTabBarControl *)control { + if((self = [super init])) { + _control = control; + _cellTrackingRects = [[NSMutableArray alloc] init]; + _closeButtonTrackingRects = [[NSMutableArray alloc] init]; + _cellFrames = [[NSMutableArray alloc] init]; _addButtonRect = NSZeroRect; - } - return self; + } + return self; } -- (void)dealloc -{ - [_cellTrackingRects release]; - [_closeButtonTrackingRects release]; - [_cellFrames release]; - [super dealloc]; +- (void)dealloc { + [_cellTrackingRects release]; + [_closeButtonTrackingRects release]; + [_cellFrames release]; + [super dealloc]; } /*! @@ -55,11 +53,10 @@ @abstract Returns the position for the add tab button. @discussion Returns the position for the add tab button. @returns The rect for the add button rect. -*/ + */ -- (NSRect)addButtonRect -{ - return _addButtonRect; +- (NSRect)addButtonRect { + return _addButtonRect; } /*! @@ -67,11 +64,10 @@ @abstract Returns current overflow menu or nil if there is none. @discussion Returns current overflow menu or nil if there is none. @returns The current overflow menu. -*/ + */ -- (NSMenu *)overflowMenu -{ - return _overflowMenu; +- (NSMenu *)overflowMenu { + return _overflowMenu; } /*! @@ -80,18 +76,17 @@ @discussion Returns the rect for the tracking rect at the requested index. @param Index of a cell. @returns The tracking rect of the cell at the requested index. -*/ - -- (NSRect)cellTrackingRectAtIndex:(NSInteger)index -{ - NSRect rect; - if (index > -1 && index < [_cellTrackingRects count]) { - rect = [[_cellTrackingRects objectAtIndex:index] rectValue]; - } else { - NSLog(@"cellTrackingRectAtIndex: Invalid index (%ld)", (long)index); - rect = NSZeroRect; - } - return rect; + */ + +- (NSRect)cellTrackingRectAtIndex:(NSInteger)index { + NSRect rect; + if(index > -1 && index < [_cellTrackingRects count]) { + rect = [[_cellTrackingRects objectAtIndex:index] rectValue]; + } else { + NSLog(@"cellTrackingRectAtIndex: Invalid index (%ld)", (long)index); + rect = NSZeroRect; + } + return rect; } /*! @@ -100,18 +95,17 @@ @discussion Returns the tracking rect for the close button at the requested index. @param Index of a cell. @returns The close button tracking rect of the cell at the requested index. -*/ - -- (NSRect)closeButtonTrackingRectAtIndex:(NSInteger)index -{ - NSRect rect; - if (index > -1 && index < [_closeButtonTrackingRects count]) { - rect = [[_closeButtonTrackingRects objectAtIndex:index] rectValue]; - } else { - NSLog(@"closeButtonTrackingRectAtIndex: Invalid index (%ld)", (long)index); - rect = NSZeroRect; - } - return rect; + */ + +- (NSRect)closeButtonTrackingRectAtIndex:(NSInteger)index { + NSRect rect; + if(index > -1 && index < [_closeButtonTrackingRects count]) { + rect = [[_closeButtonTrackingRects objectAtIndex:index] rectValue]; + } else { + NSLog(@"closeButtonTrackingRectAtIndex: Invalid index (%ld)", (long)index); + rect = NSZeroRect; + } + return rect; } /*! @@ -120,19 +114,18 @@ @discussion Returns the frame for the cell at the requested index. @param Index of a cell. @returns The frame of the cell at the requested index. -*/ - -- (NSRect)cellFrameAtIndex:(NSInteger)index -{ - NSRect rect; - - if (index > -1 && index < [_cellFrames count]) { - rect = [[_cellFrames objectAtIndex:index] rectValue]; - } else { - NSLog(@"cellFrameAtIndex: Invalid index (%ld)", (long)index); - rect = NSZeroRect; - } - return rect; + */ + +- (NSRect)cellFrameAtIndex:(NSInteger)index { + NSRect rect; + + if(index > -1 && index < [_cellFrames count]) { + rect = [[_cellFrames objectAtIndex:index] rectValue]; + } else { + NSLog(@"cellFrameAtIndex: Invalid index (%ld)", (long)index); + rect = NSZeroRect; + } + return rect; } /*! @@ -140,46 +133,45 @@ @abstract Changes the cell states so the given cell is the currently selected cell. @discussion Makes the given cell the active cell and properly recalculates the tab states for surrounding cells. @param An instance of PSMTabBarCell to make active. -*/ - -- (void)setSelectedCell:(PSMTabBarCell *)cell -{ - NSArray *cells = [_control cells]; - NSEnumerator *enumerator = [cells objectEnumerator]; - PSMTabBarCell *lastCell = nil, *nextCell; - - //deselect the previously selected tab - while ( (nextCell = [enumerator nextObject]) && ([nextCell state] == NSOffState) ) { - lastCell = nextCell; - } - - [nextCell setState:NSOffState]; - [nextCell setTabState:PSMTab_PositionMiddleMask]; - - if (lastCell && lastCell != [_control lastVisibleTab]) { - [lastCell setTabState:~[lastCell tabState] & PSMTab_RightIsSelectedMask]; - } - - if ( (nextCell = [enumerator nextObject]) ) { - [nextCell setTabState:~[lastCell tabState] & PSMTab_LeftIsSelectedMask]; - } - - [cell setState:NSOnState]; - [cell setTabState:PSMTab_SelectedMask]; - - if (![cell isInOverflowMenu]) { - NSInteger cellIndex = [cells indexOfObject:cell]; - - if (cellIndex > 0) { - nextCell = [cells objectAtIndex:cellIndex - 1]; - [nextCell setTabState:[nextCell tabState] | PSMTab_RightIsSelectedMask]; - } - - if (cellIndex < [cells count] - 1) { - nextCell = [cells objectAtIndex:cellIndex + 1]; - [nextCell setTabState:[nextCell tabState] | PSMTab_LeftIsSelectedMask]; - } - } + */ + +- (void)setSelectedCell:(PSMTabBarCell *)cell { + NSArray *cells = [_control cells]; + NSEnumerator *enumerator = [cells objectEnumerator]; + PSMTabBarCell *lastCell = nil, *nextCell; + + //deselect the previously selected tab + while((nextCell = [enumerator nextObject]) && ([nextCell state] == NSOffState)) { + lastCell = nextCell; + } + + [nextCell setState:NSOffState]; + [nextCell setTabState:PSMTab_PositionMiddleMask]; + + if(lastCell && lastCell != [_control lastVisibleTab]) { + [lastCell setTabState:~[lastCell tabState] & PSMTab_RightIsSelectedMask]; + } + + if((nextCell = [enumerator nextObject])) { + [nextCell setTabState:~[lastCell tabState] & PSMTab_LeftIsSelectedMask]; + } + + [cell setState:NSOnState]; + [cell setTabState:PSMTab_SelectedMask]; + + if(![cell isInOverflowMenu]) { + NSInteger cellIndex = [cells indexOfObject:cell]; + + if(cellIndex > 0) { + nextCell = [cells objectAtIndex:cellIndex - 1]; + [nextCell setTabState:[nextCell tabState] | PSMTab_RightIsSelectedMask]; + } + + if(cellIndex < [cells count] - 1) { + nextCell = [cells objectAtIndex:cellIndex + 1]; + [nextCell setTabState:[nextCell tabState] | PSMTab_LeftIsSelectedMask]; + } + } } /*! @@ -187,47 +179,45 @@ @abstract Recalculates cell positions and states. @discussion This method calculates the proper frame, tabState and overflow menu status for all cells in the tab bar control. -*/ - -- (void)layoutCells -{ - NSArray *cells = [_control cells]; - NSInteger cellCount = [cells count]; - - // make sure all of our tabs are accounted for before updating - if ([[_control tabView] numberOfTabViewItems] != cellCount) { - return; - } - - [_cellTrackingRects removeAllObjects]; - [_closeButtonTrackingRects removeAllObjects]; - [_cellFrames removeAllObjects]; - - NSArray *cellWidths = [self _generateWidthsFromCells:cells]; - [self _setupCells:cells withWidths:cellWidths]; - - //set up the rect from the add tab button - _addButtonRect = [_control genericCellRect]; - _addButtonRect.size = [[_control addTabButton] frame].size; - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - _addButtonRect.origin.y = MARGIN_Y; - _addButtonRect.origin.x += [[cellWidths valueForKeyPath:@"@sum.floatValue"] doubleValue] + 2; - } else { - _addButtonRect.origin.x = 0; - _addButtonRect.origin.y = [[cellWidths lastObject] doubleValue]; - } + */ + +- (void)layoutCells { + NSArray *cells = [_control cells]; + NSInteger cellCount = [cells count]; + + // make sure all of our tabs are accounted for before updating + if([[_control tabView] numberOfTabViewItems] != cellCount) { + return; + } + + [_cellTrackingRects removeAllObjects]; + [_closeButtonTrackingRects removeAllObjects]; + [_cellFrames removeAllObjects]; + + NSArray *cellWidths = [self _generateWidthsFromCells:cells]; + [self _setupCells:cells withWidths:cellWidths]; + + //set up the rect from the add tab button + _addButtonRect = [_control genericCellRect]; + _addButtonRect.size = [[_control addTabButton] frame].size; + if([_control orientation] == PSMTabBarHorizontalOrientation) { + _addButtonRect.origin.y = MARGIN_Y; + _addButtonRect.origin.x += [[cellWidths valueForKeyPath:@"@sum.floatValue"] doubleValue] + 2; + } else { + _addButtonRect.origin.x = 0; + _addButtonRect.origin.y = [[cellWidths lastObject] doubleValue]; + } } /*! * @method _shrinkWidths:towardMinimum:withAvailableWidth: - * @abstract Decreases widths in an array toward a minimum until they fit within availableWidth, if possible + * @abstract Decreases widths in an array toward a minimum until they fit within availableWidth, if possible * @param An array of NSNumbers * @param The target minimum * @param The maximum available width * @returns The amount by which the total array width was shrunk */ -- (NSInteger)_shrinkWidths:(NSMutableArray *)newWidths towardMinimum:(NSInteger)minimum withAvailableWidth:(CGFloat)availableWidth -{ +- (NSInteger)_shrinkWidths:(NSMutableArray *)newWidths towardMinimum:(NSInteger)minimum withAvailableWidth:(CGFloat)availableWidth { BOOL changed = NO; NSInteger count = [newWidths count]; NSInteger totalWidths = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; @@ -235,45 +225,43 @@ do { changed = NO; - - for (NSInteger q = (count - 1); q >= 0; q--) { + + for(NSInteger q = (count - 1); q >= 0; q--) { CGFloat cellWidth = [[newWidths objectAtIndex:q] doubleValue]; - if (cellWidth - 1 >= minimum) { + if(cellWidth - 1 >= minimum) { cellWidth--; totalWidths--; - [newWidths replaceObjectAtIndex:q - withObject:[NSNumber numberWithDouble:cellWidth]]; + [newWidths replaceObjectAtIndex:q + withObject:[NSNumber numberWithDouble:cellWidth]]; changed = YES; - } + } } + } while(changed && (totalWidths > availableWidth)); - } while (changed && (totalWidths > availableWidth)); - - return (originalTotalWidths - totalWidths); + return(originalTotalWidths - totalWidths); } /*! * @function potentialMinimumForArray() * @abstract Calculate the minimum total for a given array of widths * @discussion The array is summed using, for each item, the minimum between the current value and the passed minimum value. - * This is useful for getting a sum if the array has size-to-fit widths which will be allowed to be less than the + * This is useful for getting a sum if the array has size-to-fit widths which will be allowed to be less than the * specified minimum. * @param An array of widths * @param The minimum * @returns The smallest possible sum for the array */ -static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) -{ +static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum){ NSInteger runningTotal = 0; NSInteger count = [array count]; - for (NSInteger i = 0; i < count; i++) { + for(NSInteger i = 0; i < count; i++) { NSInteger currentValue = [[array objectAtIndex:i] integerValue]; runningTotal += MIN(currentValue, minimum); } - + return runningTotal; } @@ -284,60 +272,59 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) visible. Uses large blocks of code that were previously in PSMTabBarControl's update method. @param An array of PSMTabBarCells. @returns An array of numbers representing the widths of cells that would be visible. -*/ - -- (NSArray *)_generateWidthsFromCells:(NSArray *)cells -{ - NSInteger cellCount = [cells count], i, numberOfVisibleCells = ([_control orientation] == PSMTabBarHorizontalOrientation) ? 1 : 0; - NSMutableArray *newWidths = [NSMutableArray arrayWithCapacity:cellCount]; - id style = [_control style]; - CGFloat availableWidth = [_control availableCellWidth], currentOrigin = 0, totalOccupiedWidth = 0.0, width; - NSRect cellRect = [_control genericCellRect], controlRect = [_control frame]; - PSMTabBarCell *currentCell; - - if ([_control orientation] == PSMTabBarVerticalOrientation) { - currentOrigin = [style topMarginForTabBarControl]; - } + */ + +- (NSArray *)_generateWidthsFromCells:(NSArray *)cells { + NSInteger cellCount = [cells count], i, numberOfVisibleCells = ([_control orientation] == PSMTabBarHorizontalOrientation) ? 1 : 0; + NSMutableArray *newWidths = [NSMutableArray arrayWithCapacity:cellCount]; + id style = [_control style]; + CGFloat availableWidth = [_control availableCellWidth], currentOrigin = 0, totalOccupiedWidth = 0.0, width; + NSRect cellRect = [_control genericCellRect], controlRect = [_control frame]; + PSMTabBarCell *currentCell; + + if([_control orientation] == PSMTabBarVerticalOrientation) { + currentOrigin = [style topMarginForTabBarControl]; + } //Don't let cells overlap the add tab button if it is visible - if ([_control showAddTabButton]) { + if([_control showAddTabButton]) { availableWidth -= [self addButtonRect].size.width; } - for (i = 0; i < cellCount; i++) { - currentCell = [cells objectAtIndex:i]; - + for(i = 0; i < cellCount; i++) { + currentCell = [cells objectAtIndex:i]; + // supress close button? - [currentCell setCloseButtonSuppressed:((cellCount == 1 && [_control canCloseOnlyTab] == NO) || + [currentCell setCloseButtonSuppressed:((cellCount == 1 && [_control canCloseOnlyTab] == NO) || [_control disableTabClose] || - ([[_control delegate] respondsToSelector:@selector(tabView:disableTabCloseForTabViewItem:)] && - [[_control delegate] tabView:[_control tabView] disableTabCloseForTabViewItem:[currentCell representedObject]]))]; - - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - // Determine cell width - if ([_control sizeCellsToFit]) { + ([[_control delegate] respondsToSelector:@selector(tabView:disableTabCloseForTabViewItem:)] && + [[_control delegate] tabView:[_control tabView] disableTabCloseForTabViewItem:[currentCell representedObject]]))]; + + if([_control orientation] == PSMTabBarHorizontalOrientation) { + // Determine cell width + if([_control sizeCellsToFit]) { width = [currentCell desiredWidthOfCell]; - if (width > [_control cellMaxWidth]) { + if(width > [_control cellMaxWidth]) { width = [_control cellMaxWidth]; } } else { width = [_control cellOptimumWidth]; } - + width = ceil(width); - + //check to see if there is not enough space to place all tabs as preferred - if (totalOccupiedWidth + width >= availableWidth) { + if(totalOccupiedWidth + width >= availableWidth) { //There's not enough space to add currentCell at its preferred width! - + //If we're not going to use the overflow menu, cram all the tab cells into the bar regardless of minimum width - if (![_control useOverflowMenu]) { + if(![_control useOverflowMenu]) { NSInteger j, averageWidth = (availableWidth / cellCount); - + numberOfVisibleCells = cellCount; [newWidths removeAllObjects]; - - for (j = 0; j < cellCount; j++) { + + for(j = 0; j < cellCount; j++) { CGFloat desiredWidth = [[cells objectAtIndex:j] desiredWidthOfCell]; [newWidths addObject:[NSNumber numberWithDouble:(desiredWidth < averageWidth && [_control sizeCellsToFit]) ? desiredWidth : averageWidth]]; } @@ -345,23 +332,23 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) totalOccupiedWidth = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; break; } - + //We'll be using the overflow menu if needed. numberOfVisibleCells = i; - if ([_control sizeCellsToFit]) { + if([_control sizeCellsToFit]) { BOOL remainingCellsMustGoToOverflow = NO; totalOccupiedWidth = [[newWidths valueForKeyPath:@"@sum.intValue"] integerValue]; - + /* Can I squeeze it in without violating min cell width? This is the width we would take up * if every cell so far were at the control minimum size (or their current size if that is less than the control minimum). - */ - if ((potentialMinimumForArray(newWidths, [_control cellMinWidth]) + MIN(width, [_control cellMinWidth])) <= availableWidth) { + */ + if((potentialMinimumForArray(newWidths, [_control cellMinWidth]) + MIN(width, [_control cellMinWidth])) <= availableWidth) { /* It's definitely possible for cells so far to be visible. * Shrink other cells to allow this one to fit */ NSInteger cellMinWidth = [_control cellMinWidth]; - + /* Start off adding it to the array; we know that it will eventually fit because * (the potential minimum <= availableWidth) * @@ -371,45 +358,45 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) numberOfVisibleCells++; totalOccupiedWidth += width; - + //First, try to shrink tabs toward the average. Tabs smaller than average won't change totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:[[newWidths valueForKeyPath:@"@avg.intValue"] integerValue] + towardMinimum:[[newWidths valueForKeyPath:@"@avg.intValue"] integerValue] withAvailableWidth:availableWidth]; - - if (totalOccupiedWidth > availableWidth) { + + if(totalOccupiedWidth > availableWidth) { //Next, shrink tabs toward the smallest of the existing tabs. The smallest tab won't change. NSInteger smallestTabWidth = [[newWidths valueForKeyPath:@"@min.intValue"] integerValue]; - if (smallestTabWidth > cellMinWidth) { + if(smallestTabWidth > cellMinWidth) { totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:smallestTabWidth + towardMinimum:smallestTabWidth withAvailableWidth:availableWidth]; } } - - if (totalOccupiedWidth > availableWidth) { + + if(totalOccupiedWidth > availableWidth) { //Finally, shrink tabs toward the imposed minimum size. All tabs larger than the minimum wll change. totalOccupiedWidth -= [self _shrinkWidths:newWidths - towardMinimum:cellMinWidth + towardMinimum:cellMinWidth withAvailableWidth:availableWidth]; } - if (totalOccupiedWidth > availableWidth) { + if(totalOccupiedWidth > availableWidth) { NSLog(@"**** -[PSMTabBarController generateWidthsFromCells:] This is a failure (available %f, total %f, width is %f)", availableWidth, totalOccupiedWidth, width); remainingCellsMustGoToOverflow = YES; } - - if (totalOccupiedWidth < availableWidth) { + + if(totalOccupiedWidth < availableWidth) { /* We're not using all available space not but exceeded available width before; * stretch all cells to fully fit the bar */ NSInteger leftoverWidth = availableWidth - totalOccupiedWidth; - if (leftoverWidth > 0) { + if(leftoverWidth > 0) { NSInteger q; - for (q = numberOfVisibleCells - 1; q >= 0; q--) { + for(q = numberOfVisibleCells - 1; q >= 0; q--) { NSInteger desiredAddition = (NSInteger)leftoverWidth / (q + 1); NSInteger newCellWidth = (NSInteger)[[newWidths objectAtIndex:q] doubleValue] + desiredAddition; [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:newCellWidth]]; @@ -418,34 +405,32 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) } } } - } else { // stretch - distribute leftover room among cells, since we can't add this cell NSInteger leftoverWidth = availableWidth - totalOccupiedWidth; NSInteger q; - for (q = i - 1; q >= 0; q--) { + for(q = i - 1; q >= 0; q--) { NSInteger desiredAddition = (NSInteger)leftoverWidth / (q + 1); NSInteger newCellWidth = (NSInteger)[[newWidths objectAtIndex:q] doubleValue] + desiredAddition; [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:newCellWidth]]; leftoverWidth -= desiredAddition; } - + remainingCellsMustGoToOverflow = YES; } // done assigning widths; remaining cells go in overflow menu - if (remainingCellsMustGoToOverflow) { + if(remainingCellsMustGoToOverflow) { break; } - } else { //We're not using size-to-fit NSInteger revisedWidth = availableWidth / (i + 1); - if (revisedWidth >= [_control cellMinWidth]) { + if(revisedWidth >= [_control cellMinWidth]) { NSUInteger q; totalOccupiedWidth = 0; - for (q = 0; q < [newWidths count]; q++) { + for(q = 0; q < [newWidths count]; q++) { [newWidths replaceObjectAtIndex:q withObject:[NSNumber numberWithDouble:revisedWidth]]; totalOccupiedWidth += revisedWidth; } @@ -464,42 +449,41 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) [newWidths addObject:[NSNumber numberWithDouble:width]]; totalOccupiedWidth += width; } - - } else { - //lay out vertical tabs - if (currentOrigin + cellRect.size.height <= controlRect.size.height) { + } else { + //lay out vertical tabs + if(currentOrigin + cellRect.size.height <= controlRect.size.height) { [newWidths addObject:[NSNumber numberWithDouble:currentOrigin]]; numberOfVisibleCells++; currentOrigin += cellRect.size.height; } else { //out of room, the remaining tabs go into overflow - if ([newWidths count] > 0 && controlRect.size.height - currentOrigin < 17) { + if([newWidths count] > 0 && controlRect.size.height - currentOrigin < 17) { [newWidths removeLastObject]; numberOfVisibleCells--; } break; } - } - } + } + } //make sure there are at least two items in the horizontal tab bar - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - if (numberOfVisibleCells < 2 && [cells count] > 1) { + if([_control orientation] == PSMTabBarHorizontalOrientation) { + if(numberOfVisibleCells < 2 && [cells count] > 1) { PSMTabBarCell *cell1 = [cells objectAtIndex:0], *cell2 = [cells objectAtIndex:1]; NSNumber *cellWidth; - + [newWidths removeAllObjects]; totalOccupiedWidth = 0; - - cellWidth = [NSNumber numberWithDouble:[cell1 desiredWidthOfCell] < availableWidth * 0.5f ? [cell1 desiredWidthOfCell] : availableWidth * 0.5f]; + + cellWidth = [NSNumber numberWithDouble:[cell1 desiredWidthOfCell] < availableWidth * 0.5f ?[cell1 desiredWidthOfCell] : availableWidth * 0.5f]; [newWidths addObject:cellWidth]; totalOccupiedWidth += [cellWidth doubleValue]; - - cellWidth = [NSNumber numberWithDouble:[cell2 desiredWidthOfCell] < (availableWidth - totalOccupiedWidth) ? [cell2 desiredWidthOfCell] : (availableWidth - totalOccupiedWidth)]; + + cellWidth = [NSNumber numberWithDouble:[cell2 desiredWidthOfCell] < (availableWidth - totalOccupiedWidth) ?[cell2 desiredWidthOfCell] : (availableWidth - totalOccupiedWidth)]; [newWidths addObject:cellWidth]; totalOccupiedWidth += [cellWidth doubleValue]; - - if (totalOccupiedWidth < availableWidth) { + + if(totalOccupiedWidth < availableWidth) { [newWidths replaceObjectAtIndex:0 withObject:[NSNumber numberWithDouble:availableWidth - [cellWidth doubleValue]]]; } @@ -507,136 +491,132 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) } } - return newWidths; + return newWidths; } /*! @method _setupCells:withWidths @abstract Creates tracking rect arrays and sets the frames of the visible cells. @discussion Creates tracking rect arrays and sets the cells given in the widths array. -*/ - -- (void)_setupCells:(NSArray *)cells withWidths:(NSArray *)widths -{ - NSInteger i, tabState, cellCount = [cells count]; - NSRect cellRect = [_control genericCellRect]; - PSMTabBarCell *cell; - NSTabViewItem *selectedTabViewItem = [[_control tabView] selectedTabViewItem]; - NSMenuItem *menuItem; - - [_overflowMenu release], _overflowMenu = nil; - - for (i = 0; i < cellCount; i++) { - cell = [cells objectAtIndex:i]; - - if (i < [widths count]) { - tabState = 0; - - // set cell frame - if ([_control orientation] == PSMTabBarHorizontalOrientation) { - cellRect.size.width = [[widths objectAtIndex:i] doubleValue]; - } else { - cellRect.size.width = [_control frame].size.width; - cellRect.origin.y = [[widths objectAtIndex:i] doubleValue]; - cellRect.origin.x = 0; - } - - [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; - - //add tracking rects to arrays - [_closeButtonTrackingRects addObject:[NSValue valueWithRect:[cell closeButtonRectForFrame:cellRect]]]; - [_cellTrackingRects addObject:[NSValue valueWithRect:cellRect]]; - - if ([[cell representedObject] isEqualTo:selectedTabViewItem]) { - [cell setState:NSOnState]; - tabState |= PSMTab_SelectedMask; - // previous cell - if (i > 0) { - [[cells objectAtIndex:i - 1] setTabState:([(PSMTabBarCell *)[cells objectAtIndex:i - 1] tabState] | PSMTab_RightIsSelectedMask)]; - } - // next cell - see below - } else { - [cell setState:NSOffState]; - // see if prev cell was selected - if ( (i > 0) && ([[cells objectAtIndex:i - 1] state] == NSOnState) ) { - tabState |= PSMTab_LeftIsSelectedMask; - } - } - - // more tab states - if ([widths count] == 1) { - tabState |= PSMTab_PositionLeftMask | PSMTab_PositionRightMask | PSMTab_PositionSingleMask; - } else if (i == 0) { - tabState |= PSMTab_PositionLeftMask; - } else if (i == [widths count] - 1) { - tabState |= PSMTab_PositionRightMask; - } - - [cell setTabState:tabState]; - [cell setIsInOverflowMenu:NO]; - - // indicator - if (![[cell indicator] isHidden] && ![_control isTabBarHidden]) { - if (![[_control subviews] containsObject:[cell indicator]]) { - [_control addSubview:[cell indicator]]; - [[cell indicator] startAnimation:self]; - } - } - - // next... - cellRect.origin.x += [[widths objectAtIndex:i] doubleValue]; - } else { - [cell setState:NSOffState]; - [cell setIsInOverflowMenu:YES]; - [[cell indicator] removeFromSuperview]; - + */ + +- (void)_setupCells:(NSArray *)cells withWidths:(NSArray *)widths { + NSInteger i, tabState, cellCount = [cells count]; + NSRect cellRect = [_control genericCellRect]; + PSMTabBarCell *cell; + NSTabViewItem *selectedTabViewItem = [[_control tabView] selectedTabViewItem]; + NSMenuItem *menuItem; + + [_overflowMenu release], _overflowMenu = nil; + + for(i = 0; i < cellCount; i++) { + cell = [cells objectAtIndex:i]; + + if(i < [widths count]) { + tabState = 0; + + // set cell frame + if([_control orientation] == PSMTabBarHorizontalOrientation) { + cellRect.size.width = [[widths objectAtIndex:i] doubleValue]; + } else { + cellRect.size.width = [_control frame].size.width; + cellRect.origin.y = [[widths objectAtIndex:i] doubleValue]; + cellRect.origin.x = 0; + } + + [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; + + //add tracking rects to arrays + [_closeButtonTrackingRects addObject:[NSValue valueWithRect:[cell closeButtonRectForFrame:cellRect]]]; + [_cellTrackingRects addObject:[NSValue valueWithRect:cellRect]]; + + if([[cell representedObject] isEqualTo:selectedTabViewItem]) { + [cell setState:NSOnState]; + tabState |= PSMTab_SelectedMask; + // previous cell + if(i > 0) { + [[cells objectAtIndex:i - 1] setTabState:([(PSMTabBarCell *)[cells objectAtIndex:i - 1] tabState] | PSMTab_RightIsSelectedMask)]; + } + // next cell - see below + } else { + [cell setState:NSOffState]; + // see if prev cell was selected + if((i > 0) && ([[cells objectAtIndex:i - 1] state] == NSOnState)) { + tabState |= PSMTab_LeftIsSelectedMask; + } + } + + // more tab states + if([widths count] == 1) { + tabState |= PSMTab_PositionLeftMask | PSMTab_PositionRightMask | PSMTab_PositionSingleMask; + } else if(i == 0) { + tabState |= PSMTab_PositionLeftMask; + } else if(i == [widths count] - 1) { + tabState |= PSMTab_PositionRightMask; + } + + [cell setTabState:tabState]; + [cell setIsInOverflowMenu:NO]; + + // indicator + if(![[cell indicator] isHidden] && ![_control isTabBarHidden]) { + if(![[_control subviews] containsObject:[cell indicator]]) { + [_control addSubview:[cell indicator]]; + [[cell indicator] startAnimation:self]; + } + } + + // next... + cellRect.origin.x += [[widths objectAtIndex:i] doubleValue]; + } else { + [cell setState:NSOffState]; + [cell setIsInOverflowMenu:YES]; + [[cell indicator] removeFromSuperview]; + //position the cell well offscreen - if ([_control orientation] == PSMTabBarHorizontalOrientation) { + if([_control orientation] == PSMTabBarHorizontalOrientation) { cellRect.origin.x += [[_control style] rightMarginForTabBarControl] + 20; } else { cellRect.origin.y = [_control frame].size.height + 2; } - - [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; - - if (_overflowMenu == nil) { - _overflowMenu = [[NSMenu alloc] init]; - [_overflowMenu insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:0]; // Because the overflowPupUpButton is a pull down menu + + [_cellFrames addObject:[NSValue valueWithRect:cellRect]]; + + if(_overflowMenu == nil) { + _overflowMenu = [[NSMenu alloc] init]; + [_overflowMenu insertItemWithTitle:@"" action:nil keyEquivalent:@"" atIndex:0]; // Because the overflowPupUpButton is a pull down menu [_overflowMenu setDelegate:self]; - } - + } + // Each item's title is limited to 60 characters. If more than 60 characters, use an ellipsis to indicate that more exists. - menuItem = [_overflowMenu addItemWithTitle:[[[cell attributedStringValue] string] stringWithEllipsisByTruncatingToLength:MAX_OVERFLOW_MENUITEM_TITLE_LENGTH] - action:@selector(overflowMenuAction:) - keyEquivalent:@""]; - [menuItem setTarget:_control]; - [menuItem setRepresentedObject:[cell representedObject]]; - - if ([cell count] > 0) { - [menuItem setTitle:[[menuItem title] stringByAppendingFormat:@" (%lu)", (unsigned long)[cell count]]]; + menuItem = [_overflowMenu addItemWithTitle:[[[cell attributedStringValue] string] stringWithEllipsisByTruncatingToLength:MAX_OVERFLOW_MENUITEM_TITLE_LENGTH] + action:@selector(overflowMenuAction:) + keyEquivalent:@""]; + [menuItem setTarget:_control]; + [menuItem setRepresentedObject:[cell representedObject]]; + + if([cell count] > 0) { + [menuItem setTitle:[[menuItem title] stringByAppendingFormat:@" (%lu)", (unsigned long)[cell count]]]; } - } - } + } + } } -- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)menuItem atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel -{ - if (menu == _overflowMenu) { - if ([[[menuItem representedObject] identifier] respondsToSelector:@selector(icon)]) { +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)menuItem atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel { + if(menu == _overflowMenu) { + if([[[menuItem representedObject] identifier] respondsToSelector:@selector(icon)]) { [menuItem setImage:[[[menuItem representedObject] identifier] valueForKey:@"icon"]]; } } - + return TRUE; } -- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu -{ - if (menu == _overflowMenu) { +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu { + if(menu == _overflowMenu) { return [_overflowMenu numberOfItems]; - } else { - NSLog(@"Warning: Unexpected menu delegate call for menu %@",menu); + NSLog(@"Warning: Unexpected menu delegate call for menu %@", menu); return 0; } } @@ -644,20 +624,20 @@ static NSInteger potentialMinimumForArray(NSArray *array, NSInteger minimum) @end /* -PSMTabBarController will store what the current tab frame state should be like based off the last layout. PSMTabBarControl -has to handle fetching the new frame and then changing the tab cell frame. + PSMTabBarController will store what the current tab frame state should be like based off the last layout. PSMTabBarControl + has to handle fetching the new frame and then changing the tab cell frame. Tab states will probably be changed immediately. -Tabs that aren't going to be visible need to have their frame set offscreen. Treat them as if they were visible. + Tabs that aren't going to be visible need to have their frame set offscreen. Treat them as if they were visible. -The overflow menu is rebuilt and stored by the controller. + The overflow menu is rebuilt and stored by the controller. -Arrays of tracking rects will be created here, but not applied. + Arrays of tracking rects will be created here, but not applied. Tracking rects are removed and added by PSMTabBarControl at the end of an animate/display cycle. -The add tab button frame is handled by this controller. Visibility and location are set by the control. + The add tab button frame is handled by this controller. Visibility and location are set by the control. -isInOverflowMenu should probably be removed in favor of a call that returns yes/no to if a cell is in overflow. (Not yet implemented) + isInOverflowMenu should probably be removed in favor of a call that returns yes/no to if a cell is in overflow. (Not yet implemented) -Still need to rewrite most of the code in PSMTabDragAssistant. -*/ + Still need to rewrite most of the code in PSMTabDragAssistant. + */ diff --git a/cocoa/PSMTabBarControl/PSMTabDragAssistant.h b/cocoa/PSMTabBarControl/PSMTabDragAssistant.h index 07703b7d3..30965f943 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragAssistant.h +++ b/cocoa/PSMTabBarControl/PSMTabDragAssistant.h @@ -7,7 +7,7 @@ // /* - This class is a sigleton that manages the details of a tab drag and drop. The details were beginning to overwhelm me when keeping all of this in the control and cells :-) + This class is a sigleton that manages the details of a tab drag and drop. The details were beginning to overwhelm me when keeping all of this in the control and cells :-) */ #import @@ -18,25 +18,26 @@ @class PSMTabBarCell, PSMTabDragWindowController; @interface PSMTabDragAssistant : NSObject { - PSMTabBarControl *_sourceTabBar; - PSMTabBarControl *_destinationTabBar; - NSMutableSet *_participatingTabBars; - PSMTabBarCell *_draggedCell; - NSInteger _draggedCellIndex; // for snap back - BOOL _isDragging; - + PSMTabBarControl *_sourceTabBar; + PSMTabBarControl *_destinationTabBar; + NSMutableSet *_participatingTabBars; + PSMTabBarCell *_draggedCell; + NSInteger _draggedCellIndex; // for snap back + BOOL _isDragging; + // Support for dragging into new windows - PSMTabDragWindowController *_draggedTab, *_draggedView; - NSSize _dragWindowOffset; - NSTimer *_fadeTimer; - BOOL _centersDragWindows; - PSMTabBarTearOffStyle _currentTearOffStyle; - - // Animation - NSTimer *_animationTimer; - NSMutableArray *_sineCurveWidths; - NSPoint _currentMouseLoc; - PSMTabBarCell *_targetCell; + PSMTabDragWindowController *_draggedTab; + PSMTabDragWindowController *_draggedView; + NSSize _dragWindowOffset; + NSTimer *_fadeTimer; + BOOL _centersDragWindows; + PSMTabBarTearOffStyle _currentTearOffStyle; + + // Animation + NSTimer *_animationTimer; + NSMutableArray *_sineCurveWidths; + NSPoint _currentMouseLoc; + PSMTabBarCell *_targetCell; } // Creation/destruction @@ -64,7 +65,7 @@ - (void)draggingUpdatedInTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc; - (void)draggingExitedTabBar:(PSMTabBarControl *)control; - (void)performDragOperation; -- (void)draggedImageEndedAt:(NSPoint)aPoint operation:(NSDragOperation)operation; +- (void)draggedImageEndedAt:(NSPoint) aPoint operation:(NSDragOperation)operation; - (void)finishDrag; - (void)draggingBeganAt:(NSPoint)aPoint; @@ -86,14 +87,14 @@ - (id)style; - (NSMutableArray *)cells; - (void)setControlView:(id)view; -- (id)cellForPoint:(NSPoint)point cellFrame:(NSRectPointer)outFrame; +- (id)cellForPoint:(NSPoint) point cellFrame:(NSRectPointer)outFrame; - (PSMTabBarCell *)lastVisibleTab; - (NSInteger)numberOfVisibleTabs; @end void CGContextCopyWindowCaptureContentsToRect(void *grafport, CGRect rect, NSInteger cid, NSInteger wid, NSInteger zero); -OSStatus CGSSetWindowTransform(NSInteger cid, NSInteger wid, CGAffineTransform transform); +OSStatus CGSSetWindowTransform(NSInteger cid, NSInteger wid, CGAffineTransform transform); @interface NSApplication (CoreGraphicsUndocumented) - (NSInteger)contextID; diff --git a/cocoa/PSMTabBarControl/PSMTabDragAssistant.m b/cocoa/PSMTabBarControl/PSMTabDragAssistant.m index b592ce046..82a063afa 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragAssistant.m +++ b/cocoa/PSMTabBarControl/PSMTabDragAssistant.m @@ -30,285 +30,263 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; #pragma mark - #pragma mark Creation/Destruction -+ (PSMTabDragAssistant *)sharedDragAssistant -{ - if (!sharedDragAssistant) { - sharedDragAssistant = [[PSMTabDragAssistant alloc] init]; - } - - return sharedDragAssistant; -} - -- (id)init -{ - if ( (self = [super init]) ) { - _sourceTabBar = nil; - _destinationTabBar = nil; - _participatingTabBars = [[NSMutableSet alloc] init]; - _draggedCell = nil; - _animationTimer = nil; - _sineCurveWidths = [[NSMutableArray alloc] initWithCapacity:kPSMTabDragAnimationSteps]; - _targetCell = nil; - _isDragging = NO; - } - - return self; -} - -- (void)dealloc -{ - [_sourceTabBar release]; - [_destinationTabBar release]; - [_participatingTabBars release]; - [_draggedCell release]; - [_animationTimer release]; - [_sineCurveWidths release]; - [_targetCell release]; - [super dealloc]; ++ (PSMTabDragAssistant *)sharedDragAssistant { + if(!sharedDragAssistant) { + sharedDragAssistant = [[PSMTabDragAssistant alloc] init]; + } + + return sharedDragAssistant; +} + +- (id)init { + if((self = [super init])) { + _sourceTabBar = nil; + _destinationTabBar = nil; + _participatingTabBars = [[NSMutableSet alloc] init]; + _draggedCell = nil; + _animationTimer = nil; + _sineCurveWidths = [[NSMutableArray alloc] initWithCapacity:kPSMTabDragAnimationSteps]; + _targetCell = nil; + _isDragging = NO; + } + + return self; +} + +- (void)dealloc { + [_sourceTabBar release]; + [_destinationTabBar release]; + [_participatingTabBars release]; + [_draggedCell release]; + [_animationTimer release]; + [_sineCurveWidths release]; + [_targetCell release]; + [super dealloc]; } #pragma mark - #pragma mark Accessors -- (PSMTabBarControl *)sourceTabBar -{ - return _sourceTabBar; +- (PSMTabBarControl *)sourceTabBar { + return _sourceTabBar; } -- (void)setSourceTabBar:(PSMTabBarControl *)tabBar -{ - [tabBar retain]; - [_sourceTabBar release]; - _sourceTabBar = tabBar; +- (void)setSourceTabBar:(PSMTabBarControl *)tabBar { + [tabBar retain]; + [_sourceTabBar release]; + _sourceTabBar = tabBar; } -- (PSMTabBarControl *)destinationTabBar -{ - return _destinationTabBar; +- (PSMTabBarControl *)destinationTabBar { + return _destinationTabBar; } -- (void)setDestinationTabBar:(PSMTabBarControl *)tabBar -{ - [tabBar retain]; - [_destinationTabBar release]; - _destinationTabBar = tabBar; +- (void)setDestinationTabBar:(PSMTabBarControl *)tabBar { + [tabBar retain]; + [_destinationTabBar release]; + _destinationTabBar = tabBar; } -- (PSMTabBarCell *)draggedCell -{ - return _draggedCell; +- (PSMTabBarCell *)draggedCell { + return _draggedCell; } -- (void)setDraggedCell:(PSMTabBarCell *)cell -{ - [cell retain]; - [_draggedCell release]; - _draggedCell = cell; +- (void)setDraggedCell:(PSMTabBarCell *)cell { + [cell retain]; + [_draggedCell release]; + _draggedCell = cell; } -- (NSInteger)draggedCellIndex -{ - return _draggedCellIndex; +- (NSInteger)draggedCellIndex { + return _draggedCellIndex; } -- (void)setDraggedCellIndex:(NSInteger)value -{ - _draggedCellIndex = value; +- (void)setDraggedCellIndex:(NSInteger)value { + _draggedCellIndex = value; } -- (BOOL)isDragging -{ - return _isDragging; +- (BOOL)isDragging { + return _isDragging; } -- (void)setIsDragging:(BOOL)value -{ - _isDragging = value; +- (void)setIsDragging:(BOOL)value { + _isDragging = value; } -- (NSPoint)currentMouseLoc -{ - return _currentMouseLoc; +- (NSPoint)currentMouseLoc { + return _currentMouseLoc; } -- (void)setCurrentMouseLoc:(NSPoint)point -{ - _currentMouseLoc = point; +- (void)setCurrentMouseLoc:(NSPoint)point { + _currentMouseLoc = point; } -- (PSMTabBarCell *)targetCell -{ - return _targetCell; +- (PSMTabBarCell *)targetCell { + return _targetCell; } -- (void)setTargetCell:(PSMTabBarCell *)cell -{ - [cell retain]; - [_targetCell release]; - _targetCell = cell; +- (void)setTargetCell:(PSMTabBarCell *)cell { + [cell retain]; + [_targetCell release]; + _targetCell = cell; } #pragma mark - #pragma mark Functionality -- (void)startDraggingCell:(PSMTabBarCell *)cell fromTabBar:(PSMTabBarControl *)control withMouseDownEvent:(NSEvent *)event -{ - [self setIsDragging:YES]; - [self setSourceTabBar:control]; - [self setDestinationTabBar:control]; - [_participatingTabBars addObject:control]; - [self setDraggedCell:cell]; - [self setDraggedCellIndex:[[control cells] indexOfObject:cell]]; - - NSRect cellFrame = [cell frame]; - // list of widths for animation - NSInteger i; - CGFloat cellStepSize = ([control orientation] == PSMTabBarHorizontalOrientation) ? (cellFrame.size.width + 6) : (cellFrame.size.height + 1); - for (i = 0; i < kPSMTabDragAnimationSteps - 1; i++) { - NSInteger thisWidth = (NSInteger)(cellStepSize - ((cellStepSize/2.0) + ((sin((PI/2.0) + ((CGFloat)i/(CGFloat)kPSMTabDragAnimationSteps)*PI) * cellStepSize) / 2.0))); - [_sineCurveWidths addObject:[NSNumber numberWithInteger:thisWidth]]; - } +- (void)startDraggingCell:(PSMTabBarCell *)cell fromTabBar:(PSMTabBarControl *)control withMouseDownEvent:(NSEvent *)event { + [self setIsDragging:YES]; + [self setSourceTabBar:control]; + [self setDestinationTabBar:control]; + [_participatingTabBars addObject:control]; + [self setDraggedCell:cell]; + [self setDraggedCellIndex:[[control cells] indexOfObject:cell]]; + + NSRect cellFrame = [cell frame]; + // list of widths for animation + NSInteger i; + CGFloat cellStepSize = ([control orientation] == PSMTabBarHorizontalOrientation) ? (cellFrame.size.width + 6) : (cellFrame.size.height + 1); + for(i = 0; i < kPSMTabDragAnimationSteps - 1; i++) { + NSInteger thisWidth = (NSInteger)(cellStepSize - ((cellStepSize / 2.0) + ((sin((PI / 2.0) + ((CGFloat)i / (CGFloat)kPSMTabDragAnimationSteps) * PI) * cellStepSize) / 2.0))); + [_sineCurveWidths addObject:[NSNumber numberWithInteger:thisWidth]]; + } [_sineCurveWidths addObject:[NSNumber numberWithInteger:([control orientation] == PSMTabBarHorizontalOrientation) ? cellFrame.size.width : cellFrame.size.height]]; - - // hide UI buttons - [[control overflowPopUpButton] setHidden:YES]; - [[control addTabButton] setHidden:YES]; - - [[NSCursor closedHandCursor] set]; - - NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; - NSImage *dragImage = [cell dragImage]; - [[cell indicator] removeFromSuperview]; - [self distributePlaceholdersInTabBar:control withDraggedCell:cell]; - - if ([control isFlipped]) { - cellFrame.origin.y += cellFrame.size.height; - } - [cell setHighlighted:NO]; - NSSize offset = NSZeroSize; - [pboard declareTypes:[NSArray arrayWithObjects:@"PSMTabBarControlItemPBType", nil] owner: nil]; - [pboard setString:[[NSNumber numberWithInteger:[[control cells] indexOfObject:cell]] stringValue] forType:@"PSMTabBarControlItemPBType"]; - _animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0/30.0) target:self selector:@selector(animateDrag:) userInfo:nil repeats:YES]; - + + // hide UI buttons + [[control overflowPopUpButton] setHidden:YES]; + [[control addTabButton] setHidden:YES]; + + [[NSCursor closedHandCursor] set]; + + NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSImage *dragImage = [cell dragImage]; + [[cell indicator] removeFromSuperview]; + [self distributePlaceholdersInTabBar:control withDraggedCell:cell]; + + if([control isFlipped]) { + cellFrame.origin.y += cellFrame.size.height; + } + [cell setHighlighted:NO]; + NSSize offset = NSZeroSize; + [pboard declareTypes:[NSArray arrayWithObjects:@"PSMTabBarControlItemPBType", nil] owner: nil]; + [pboard setString:[[NSNumber numberWithInteger:[[control cells] indexOfObject:cell]] stringValue] forType:@"PSMTabBarControlItemPBType"]; + _animationTimer = [NSTimer scheduledTimerWithTimeInterval:(1.0 / 30.0) target:self selector:@selector(animateDrag:) userInfo:nil repeats:YES]; + [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidBeginNotification object:nil]; - + //retain the control in case the drag operation causes the control to be released [control retain]; - - if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - [[control delegate] tabView:[control tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil]) { + + if([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && + [[control delegate] tabView:[control tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil]) { _currentTearOffStyle = [control tearOffStyle]; _draggedTab = [[PSMTabDragWindowController alloc] initWithImage:dragImage styleMask:NSBorderlessWindowMask tearOffStyle:_currentTearOffStyle]; - + cellFrame.origin.y -= cellFrame.size.height; [control dragImage:[[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] autorelease] at:cellFrame.origin offset:offset event:event pasteboard:pboard source:control slideBack:NO]; } else { [control dragImage:dragImage at:cellFrame.origin offset:offset event:event pasteboard:pboard source:control slideBack:YES]; } - + [control release]; } -- (void)draggingEnteredTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc -{ - if (_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![self destinationTabBar]) { +- (void)draggingEnteredTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc { + if(_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![self destinationTabBar]) { [_draggedTab switchImages]; } - - [self setDestinationTabBar:control]; - [self setCurrentMouseLoc:mouseLoc]; - // hide UI buttons - [[control overflowPopUpButton] setHidden:YES]; - [[control addTabButton] setHidden:YES]; - if ([[control cells] count] == 0 || ![[[control cells] objectAtIndex:0] isPlaceholder]) { - [self distributePlaceholdersInTabBar:control]; - } - [_participatingTabBars addObject:control]; - + + [self setDestinationTabBar:control]; + [self setCurrentMouseLoc:mouseLoc]; + // hide UI buttons + [[control overflowPopUpButton] setHidden:YES]; + [[control addTabButton] setHidden:YES]; + if([[control cells] count] == 0 || ![[[control cells] objectAtIndex:0] isPlaceholder]) { + [self distributePlaceholdersInTabBar:control]; + } + [_participatingTabBars addObject:control]; + //tell the drag window to display only the header if there is one - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow && _draggedView) { - if (_fadeTimer) { + if(_currentTearOffStyle == PSMTabBarTearOffAlphaWindow && _draggedView) { + if(_fadeTimer) { [_fadeTimer invalidate]; } - + [[_draggedTab window] orderFront:nil]; _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeOutDragWindow:) userInfo:nil repeats:YES]; } } -- (void)draggingUpdatedInTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc -{ - if ([self destinationTabBar] != control) { - [self setDestinationTabBar:control]; - } - [self setCurrentMouseLoc:mouseLoc]; +- (void)draggingUpdatedInTabBar:(PSMTabBarControl *)control atPoint:(NSPoint)mouseLoc { + if([self destinationTabBar] != control) { + [self setDestinationTabBar:control]; + } + [self setCurrentMouseLoc:mouseLoc]; } -- (void)draggingExitedTabBar:(PSMTabBarControl *)control -{ - if ([[control delegate] respondsToSelector:@selector(tabView:shouldAllowTabViewItem:toLeaveTabBar:)] && - ![[control delegate] tabView:[control tabView] shouldAllowTabViewItem:[[self draggedCell] representedObject] toLeaveTabBar:control]) { +- (void)draggingExitedTabBar:(PSMTabBarControl *)control { + if([[control delegate] respondsToSelector:@selector(tabView:shouldAllowTabViewItem:toLeaveTabBar:)] && + ![[control delegate] tabView:[control tabView] shouldAllowTabViewItem:[[self draggedCell] representedObject] toLeaveTabBar:control]) { return; } - [self setDestinationTabBar:nil]; - [self setCurrentMouseLoc:NSMakePoint(-1.0, -1.0)]; - - if (_fadeTimer) { + [self setDestinationTabBar:nil]; + [self setCurrentMouseLoc:NSMakePoint(-1.0, -1.0)]; + + if(_fadeTimer) { [_fadeTimer invalidate]; _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeInDragWindow:) userInfo:nil repeats:YES]; - } else if (_draggedTab) { - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { + } else if(_draggedTab) { + if(_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { //create a new floating drag window - if (!_draggedView) { + if(!_draggedView) { NSUInteger styleMask; NSImage *viewImage = [self _imageForViewOfCell:[self draggedCell] styleMask:&styleMask]; - + _draggedView = [[PSMTabDragWindowController alloc] initWithImage:viewImage styleMask:styleMask tearOffStyle:PSMTabBarTearOffAlphaWindow]; [[_draggedView window] setAlphaValue:0.0]; } - + NSPoint windowOrigin = [[control window] frame].origin; windowOrigin.x -= _dragWindowOffset.width; windowOrigin.y += _dragWindowOffset.height; [[_draggedView window] setFrameOrigin:windowOrigin]; [[_draggedView window] orderWindow:NSWindowBelow relativeTo:[[_draggedTab window] windowNumber]]; - - } else if (_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![_draggedTab alternateImage]) { + } else if(_currentTearOffStyle == PSMTabBarTearOffMiniwindow && ![_draggedTab alternateImage]) { NSImage *image; NSSize imageSize; - NSUInteger mask; //we don't need this but we can't pass nil in for the style mask, as some delegate implementations will crash - - if ( !(image = [self _miniwindowImageOfWindow:[control window]]) ) { + NSUInteger mask; //we don't need this but we can't pass nil in for the style mask, as some delegate implementations will crash + + if(!(image = [self _miniwindowImageOfWindow:[control window]])) { image = [[self _imageForViewOfCell:[self draggedCell] styleMask:&mask] copy]; } - + imageSize = [image size]; [image setScalesWhenResized:YES]; - - if (imageSize.width > imageSize.height) { + + if(imageSize.width > imageSize.height) { [image setSize:NSMakeSize(125, 125 * (imageSize.height / imageSize.width))]; } else { [image setSize:NSMakeSize(125 * (imageSize.width / imageSize.height), 125)]; } - + [_draggedTab setAlternateImage:image]; } - + //set the window's alpha mask to zero if the last tab is being dragged //don't fade out the old window if the delegate doesn't respond to the new tab bar method, just to be safe - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1 && [self sourceTabBar] == control && - [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) { + if([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1 && [self sourceTabBar] == control && + [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) { [[[self sourceTabBar] window] setAlphaValue:0.0]; - - if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { + + if([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { [[_draggedView window] setAlphaValue:kPSMTabDragWindowAlpha]; } else { - #warning fix me - what should we do when the last tab is dragged as a miniwindow? + //#warning fix me - what should we do when the last tab is dragged as a miniwindow? } } else { - if ([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { + if([_sourceTabBar tearOffStyle] == PSMTabBarTearOffAlphaWindow) { _fadeTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 / 30.0 target:self selector:@selector(fadeInDragWindow:) userInfo:nil repeats:YES]; } else { [_draggedTab switchImages]; @@ -318,203 +296,199 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; } } -- (void)performDragOperation -{ - // move cell +- (void)performDragOperation { + // move cell NSInteger destinationIndex = [[[self destinationTabBar] cells] indexOfObject:[self targetCell]]; - + //there is the slight possibility of the targetCell now being set properly, so avoid errors - if (destinationIndex >= [[[self destinationTabBar] cells] count]) { + if(destinationIndex >= [[[self destinationTabBar] cells] count]) { destinationIndex = [[[self destinationTabBar] cells] count] - 1; } - - [[[self destinationTabBar] cells] replaceObjectAtIndex:destinationIndex withObject:[self draggedCell]]; - [[self draggedCell] setControlView:[self destinationTabBar]]; - - // move actual NSTabViewItem - if ([self sourceTabBar] != [self destinationTabBar]) { + + [[[self destinationTabBar] cells] replaceObjectAtIndex:destinationIndex withObject:[self draggedCell]]; + [[self draggedCell] setControlView:[self destinationTabBar]]; + + // move actual NSTabViewItem + if([self sourceTabBar] != [self destinationTabBar]) { //remove the tracking rects and bindings registered on the old tab [[self sourceTabBar] removeTrackingRect:[[self draggedCell] closeButtonTrackingTag]]; [[self sourceTabBar] removeTrackingRect:[[self draggedCell] cellTrackingTag]]; [[self sourceTabBar] removeTabForCell:[self draggedCell]]; - + NSInteger i, insertIndex; NSArray *cells = [[self destinationTabBar] cells]; - + //find the index of where the dragged cell was just dropped - for (i = 0, insertIndex = 0; (i < [cells count]) && ([cells objectAtIndex:i] != [self draggedCell]); i++, insertIndex++) { - if ([[cells objectAtIndex:i] isPlaceholder]) { + for(i = 0, insertIndex = 0; (i < [cells count]) && ([cells objectAtIndex:i] != [self draggedCell]); i++, insertIndex++) { + if([[cells objectAtIndex:i] isPlaceholder]) { insertIndex--; } } - - [[[self sourceTabBar] tabView] removeTabViewItem:[[self draggedCell] representedObject]]; - [[[self destinationTabBar] tabView] insertTabViewItem:[[self draggedCell] representedObject] atIndex:insertIndex]; - + + [[[self sourceTabBar] tabView] removeTabViewItem:[[self draggedCell] representedObject]]; + [[[self destinationTabBar] tabView] insertTabViewItem:[[self draggedCell] representedObject] atIndex:insertIndex]; + //calculate the position for the dragged cell - if ([[self destinationTabBar] automaticallyAnimates]) { - if (insertIndex > 0) { + if([[self destinationTabBar] automaticallyAnimates]) { + if(insertIndex > 0) { NSRect cellRect = [[cells objectAtIndex:insertIndex - 1] frame]; cellRect.origin.x += cellRect.size.width; [[self draggedCell] setFrame:cellRect]; } } - + //rebind the cell to the new control [[self destinationTabBar] bindPropertiesForCell:[self draggedCell] andTabViewItem:[[self draggedCell] representedObject]]; - + //select the newly moved item in the destination tab view [[[self destinationTabBar] tabView] selectTabViewItem:[[self draggedCell] representedObject]]; - } else { + } else { //have to do this before checking the index of a cell otherwise placeholders will be counted [self removeAllPlaceholdersFromTabBar:[self sourceTabBar]]; - + //rearrange the tab view items NSTabView *tabView = [[self sourceTabBar] tabView]; NSTabViewItem *item = [[self draggedCell] representedObject]; BOOL reselect = ([tabView selectedTabViewItem] == item); NSInteger index; NSArray *cells = [[self sourceTabBar] cells]; - + //find the index of where the dragged cell was just dropped - for (index = 0; index < [cells count] && [cells objectAtIndex:index] != [self draggedCell]; index++); - + for(index = 0; index < [cells count] && [cells objectAtIndex:index] != [self draggedCell]; index++) { + ; + } + //temporarily disable the delegate in order to move the tab to a different index id tempDelegate = [tabView delegate]; [tabView setDelegate:nil]; [item retain]; [tabView removeTabViewItem:item]; [tabView insertTabViewItem:item atIndex:index]; - if (reselect) { + if(reselect) { [tabView selectTabViewItem:item]; } [tabView setDelegate:tempDelegate]; } - - if (([self sourceTabBar] != [self destinationTabBar] || [[[self sourceTabBar] cells] indexOfObject:[self draggedCell]] != _draggedCellIndex) && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { + + if(([self sourceTabBar] != [self destinationTabBar] || [[[self sourceTabBar] cells] indexOfObject:[self draggedCell]] != _draggedCellIndex) && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { [[[self sourceTabBar] delegate] tabView:[[self sourceTabBar] tabView] didDropTabViewItem:[[self draggedCell] representedObject] inTabBar:[self destinationTabBar]]; } - + [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidEndNotification object:nil]; - - [self finishDrag]; + + [self finishDrag]; } -- (void)draggedImageEndedAt:(NSPoint)aPoint operation:(NSDragOperation)operation -{ - if ([self isDragging]) { // means there was not a successful drop (performDragOperation) +- (void)draggedImageEndedAt:(NSPoint)aPoint operation:(NSDragOperation)operation { + if([self isDragging]) { // means there was not a successful drop (performDragOperation) id sourceDelegate = [[self sourceTabBar] delegate]; - + //split off the dragged tab into a new window - if ([self destinationTabBar] == nil && - sourceDelegate && [sourceDelegate respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && - [sourceDelegate tabView:[[self sourceTabBar] tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil] && - [sourceDelegate respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) { + if([self destinationTabBar] == nil && + sourceDelegate && [sourceDelegate respondsToSelector:@selector(tabView:shouldDropTabViewItem:inTabBar:)] && + [sourceDelegate tabView:[[self sourceTabBar] tabView] shouldDropTabViewItem:[[self draggedCell] representedObject] inTabBar:nil] && + [sourceDelegate respondsToSelector:@selector(tabView:newTabBarForDraggedTabViewItem:atPoint:)]) { PSMTabBarControl *control = [sourceDelegate tabView:[[self sourceTabBar] tabView] newTabBarForDraggedTabViewItem:[[self draggedCell] representedObject] atPoint:aPoint]; - - if (control) { + + if(control) { //add the dragged tab to the new window [[control cells] insertObject:[self draggedCell] atIndex:0]; - + //remove the tracking rects and bindings registered on the old tab [[self sourceTabBar] removeTrackingRect:[[self draggedCell] closeButtonTrackingTag]]; [[self sourceTabBar] removeTrackingRect:[[self draggedCell] cellTrackingTag]]; [[self sourceTabBar] removeTabForCell:[self draggedCell]]; - + //rebind the cell to the new control [control bindPropertiesForCell:[self draggedCell] andTabViewItem:[[self draggedCell] representedObject]]; - + [[self draggedCell] setControlView:control]; - + [[[self sourceTabBar] tabView] removeTabViewItem:[[self draggedCell] representedObject]]; - + [[control tabView] addTabViewItem:[[self draggedCell] representedObject]]; - [control update:NO]; //make sure the new tab is set in the correct position - - if (_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { + [control update:NO]; //make sure the new tab is set in the correct position + + if(_currentTearOffStyle == PSMTabBarTearOffAlphaWindow) { [[control window] makeKeyAndOrderFront:nil]; } else { //center the window over where we ended dragging [self _expandWindow:[control window] atPoint:[NSEvent mouseLocation]]; } - - if ([sourceDelegate respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { + + if([sourceDelegate respondsToSelector:@selector(tabView:didDropTabViewItem:inTabBar:)]) { [sourceDelegate tabView:[[self sourceTabBar] tabView] didDropTabViewItem:[[self draggedCell] representedObject] inTabBar:control]; } } else { NSLog(@"Delegate returned no control to add to."); [[[self sourceTabBar] cells] insertObject:[self draggedCell] atIndex:[self draggedCellIndex]]; } - } else { // put cell back [[[self sourceTabBar] cells] insertObject:[self draggedCell] atIndex:[self draggedCellIndex]]; } - + [[NSNotificationCenter defaultCenter] postNotificationName:PSMTabDragDidEndNotification object:nil]; - + [self finishDrag]; - } + } } -- (void)finishDrag -{ - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 0 && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:closeWindowForLastTabViewItem:)]) { +- (void)finishDrag { + if([[[self sourceTabBar] tabView] numberOfTabViewItems] == 0 && [[[self sourceTabBar] delegate] respondsToSelector:@selector(tabView:closeWindowForLastTabViewItem:)]) { [[[self sourceTabBar] delegate] tabView:[[self sourceTabBar] tabView] closeWindowForLastTabViewItem:[[self draggedCell] representedObject]]; } - - if (_draggedTab) { + + if(_draggedTab) { [[_draggedTab window] orderOut:nil]; [_draggedTab release]; _draggedTab = nil; } - - if (_draggedView) { + + if(_draggedView) { [[_draggedView window] orderOut:nil]; [_draggedView release]; _draggedView = nil; } - + _centersDragWindows = NO; - - [self setIsDragging:NO]; - [self removeAllPlaceholdersFromTabBar:[self sourceTabBar]]; - [self setSourceTabBar:nil]; - [self setDestinationTabBar:nil]; - NSEnumerator *e = [_participatingTabBars objectEnumerator]; - PSMTabBarControl *tabBar; - while ( (tabBar = [e nextObject]) ) { - [self removeAllPlaceholdersFromTabBar:tabBar]; - } - [_participatingTabBars removeAllObjects]; - [self setDraggedCell:nil]; - [_animationTimer invalidate]; - _animationTimer = nil; - [_sineCurveWidths removeAllObjects]; - [self setTargetCell:nil]; -} - -- (void)draggingBeganAt:(NSPoint)aPoint -{ - if (_draggedTab) { + + [self setIsDragging:NO]; + [self removeAllPlaceholdersFromTabBar:[self sourceTabBar]]; + [self setSourceTabBar:nil]; + [self setDestinationTabBar:nil]; + NSEnumerator *e = [_participatingTabBars objectEnumerator]; + PSMTabBarControl *tabBar; + while((tabBar = [e nextObject])) { + [self removeAllPlaceholdersFromTabBar:tabBar]; + } + [_participatingTabBars removeAllObjects]; + [self setDraggedCell:nil]; + [_animationTimer invalidate]; + _animationTimer = nil; + [_sineCurveWidths removeAllObjects]; + [self setTargetCell:nil]; +} + +- (void)draggingBeganAt:(NSPoint)aPoint { + if(_draggedTab) { [[_draggedTab window] setFrameTopLeftPoint:aPoint]; [[_draggedTab window] orderFront:nil]; - - if ([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1) { + + if([[[self sourceTabBar] tabView] numberOfTabViewItems] == 1) { [self draggingExitedTabBar:[self sourceTabBar]]; [[_draggedTab window] setAlphaValue:0.0]; } } } -- (void)draggingMovedTo:(NSPoint)aPoint -{ - if (_draggedTab) { - if (_centersDragWindows) { - if ([_draggedTab isAnimating]) { +- (void)draggingMovedTo:(NSPoint)aPoint { + if(_draggedTab) { + if(_centersDragWindows) { + if([_draggedTab isAnimating]) { return; } - + //Ignore aPoint, as it seems to give wacky values NSRect frame = [[_draggedTab window] frame]; frame.origin = [NSEvent mouseLocation]; @@ -524,12 +498,12 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; } else { [[_draggedTab window] setFrameTopLeftPoint:aPoint]; } - - if (_draggedView) { + + if(_draggedView) { //move the view representation with the tab //the relative position of the dragged view window will be different //depending on the position of the tab bar relative to the controlled tab view - + aPoint.y -= [[_draggedTab window] frame].size.height; aPoint.x -= _dragWindowOffset.width; aPoint.y += _dragWindowOffset.height; @@ -538,10 +512,9 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; } } -- (void)fadeInDragWindow:(NSTimer *)timer -{ +- (void)fadeInDragWindow:(NSTimer *)timer { CGFloat value = [[_draggedView window] alphaValue]; - if (value >= kPSMTabDragWindowAlpha || _draggedTab == nil) { + if(value >= kPSMTabDragWindowAlpha || _draggedTab == nil) { [timer invalidate]; _fadeTimer = nil; } else { @@ -550,19 +523,18 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; } } -- (void)fadeOutDragWindow:(NSTimer *)timer -{ +- (void)fadeOutDragWindow:(NSTimer *)timer { CGFloat value = [[_draggedView window] alphaValue]; NSWindow *tabWindow = [_draggedTab window], *viewWindow = [_draggedView window]; - - if (value <= 0.0) { + + if(value <= 0.0) { [viewWindow setAlphaValue:0.0]; [tabWindow setAlphaValue:kPSMTabDragWindowAlpha]; - + [timer invalidate]; _fadeTimer = nil; } else { - if ([tabWindow alphaValue] < kPSMTabDragWindowAlpha) { + if([tabWindow alphaValue] < kPSMTabDragWindowAlpha) { [tabWindow setAlphaValue:[tabWindow alphaValue] + kPSMTabDragAlphaInterval]; } [viewWindow setAlphaValue:value - kPSMTabDragAlphaInterval]; @@ -572,35 +544,34 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; #pragma mark - #pragma mark Private -- (NSImage *)_imageForViewOfCell:(PSMTabBarCell *)cell styleMask:(NSUInteger *)outMask -{ +- (NSImage *)_imageForViewOfCell:(PSMTabBarCell *)cell styleMask:(NSUInteger *)outMask { PSMTabBarControl *control = [cell controlView]; NSImage *viewImage = nil; - - if (outMask) { + + if(outMask) { *outMask = NSBorderlessWindowMask; } - - if ([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:imageForTabViewItem:offset:styleMask:)]) { + + if([control delegate] && [[control delegate] respondsToSelector:@selector(tabView:imageForTabViewItem:offset:styleMask:)]) { //get a custom image representation of the view to drag from the delegate NSImage *tabImage = [_draggedTab image]; NSPoint drawPoint; _dragWindowOffset = NSZeroSize; viewImage = [[control delegate] tabView:[control tabView] imageForTabViewItem:[cell representedObject] offset:&_dragWindowOffset styleMask:outMask]; [viewImage lockFocus]; - + //draw the tab into the returned window, that way we don't have two windows being dragged (this assumes the tab will be on the window) drawPoint = NSMakePoint(_dragWindowOffset.width, [viewImage size].height - _dragWindowOffset.height); - - if ([control orientation] == PSMTabBarHorizontalOrientation) { + + if([control orientation] == PSMTabBarHorizontalOrientation) { drawPoint.y += [[control style] tabCellHeight] - [tabImage size].height; _dragWindowOffset.height -= [[control style] tabCellHeight] - [tabImage size].height; } else { drawPoint.x += [control frame].size.width - [tabImage size].width; } - + [tabImage compositeToPoint:drawPoint operation:NSCompositeSourceOver]; - + [viewImage unlockFocus]; } else { //the delegate doesn't give a custom image, so use an image of the view @@ -610,33 +581,31 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; [tabView drawRect:[tabView bounds]]; [viewImage unlockFocus]; } - - if (*outMask | NSBorderlessWindowMask) { + + if(*outMask | NSBorderlessWindowMask) { _dragWindowOffset.height += 22; } - + return viewImage; } -- (NSImage *)_miniwindowImageOfWindow:(NSWindow *)window -{ +- (NSImage *)_miniwindowImageOfWindow:(NSWindow *)window { NSRect rect = [window frame]; NSImage *image = [[[NSImage alloc] initWithSize:rect.size] autorelease]; [image lockFocus]; rect.origin = NSZeroPoint; CGContextCopyWindowCaptureContentsToRect([[NSGraphicsContext currentContext] graphicsPort], *(CGRect *)&rect, [NSApp contextID], [window windowNumber], 0); [image unlockFocus]; - + return image; } -- (void)_expandWindow:(NSWindow *)window atPoint:(NSPoint)point -{ +- (void)_expandWindow:(NSWindow *)window atPoint:(NSPoint)point { NSRect frame = [window frame]; [window setFrameTopLeftPoint:NSMakePoint(point.x - frame.size.width / 2, point.y + frame.size.height / 2)]; [window setAlphaValue:0.0]; [window makeKeyAndOrderFront:nil]; - + NSAnimation *animation = [[NSAnimation alloc] initWithDuration:0.25 animationCurve:NSAnimationEaseInOut]; [animation setAnimationBlockingMode:NSAnimationNonblocking]; [animation setCurrentProgress:0.1]; @@ -645,30 +614,29 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSEventTrackingRunLoopMode]; } -- (void)_expandWindowTimerFired:(NSTimer *)timer -{ +- (void)_expandWindowTimerFired:(NSTimer *)timer { NSWindow *window = [[timer userInfo] objectForKey:@"Window"]; NSAnimation *animation = [[timer userInfo] objectForKey:@"Animation"]; CGAffineTransform transform; NSPoint translation; NSRect winFrame = [window frame]; - + translation.x = (winFrame.size.width / 2.0); translation.y = (winFrame.size.height / 2.0); transform = CGAffineTransformMakeTranslation(translation.x, translation.y); transform = CGAffineTransformScale(transform, 1.0 / [animation currentValue], 1.0 / [animation currentValue]); transform = CGAffineTransformTranslate(transform, -translation.x, -translation.y); - + translation.x = -winFrame.origin.x; translation.y = winFrame.origin.y + winFrame.size.height - [[NSScreen mainScreen] frame].size.height; - + transform = CGAffineTransformTranslate(transform, translation.x, translation.y); - + CGSSetWindowTransform([NSApp contextID], [window windowNumber], transform); - + [window setAlphaValue:[animation currentValue]]; - - if (![animation isAnimating]) { + + if(![animation isAnimating]) { [timer invalidate]; [animation release]; } @@ -677,40 +645,38 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; #pragma mark - #pragma mark Animation -- (void)animateDrag:(NSTimer *)timer -{ - NSEnumerator *e = [[[_participatingTabBars copy] autorelease] objectEnumerator]; - PSMTabBarControl *tabBar; - while ( (tabBar = [e nextObject]) ) { - [self calculateDragAnimationForTabBar:tabBar]; - [[NSRunLoop currentRunLoop] performSelector:@selector(display) target:tabBar argument:nil order:1 modes:[NSArray arrayWithObjects:@"NSEventTrackingRunLoopMode", @"NSDefaultRunLoopMode", nil]]; - } -} - -- (void)calculateDragAnimationForTabBar:(PSMTabBarControl *)control -{ - BOOL removeFlag = YES; - NSMutableArray *cells = [control cells]; - NSInteger i, cellCount = [cells count]; - CGFloat position = [control orientation] == PSMTabBarHorizontalOrientation ? [[control style] leftMarginForTabBarControl] : [[control style] topMarginForTabBarControl]; - - // identify target cell - // mouse at beginning of tabs - NSPoint mouseLoc = [self currentMouseLoc]; - if ([self destinationTabBar] == control) { - removeFlag = NO; - if (mouseLoc.x < [[control style] leftMarginForTabBarControl]) { - [self setTargetCell:[cells objectAtIndex:0]]; - } else { +- (void)animateDrag:(NSTimer *)timer { + NSEnumerator *e = [[[_participatingTabBars copy] autorelease] objectEnumerator]; + PSMTabBarControl *tabBar; + while((tabBar = [e nextObject])) { + [self calculateDragAnimationForTabBar:tabBar]; + [[NSRunLoop currentRunLoop] performSelector:@selector(display) target:tabBar argument:nil order:1 modes:[NSArray arrayWithObjects:@"NSEventTrackingRunLoopMode", @"NSDefaultRunLoopMode", nil]]; + } +} + +- (void)calculateDragAnimationForTabBar:(PSMTabBarControl *)control { + BOOL removeFlag = YES; + NSMutableArray *cells = [control cells]; + NSInteger i, cellCount = [cells count]; + CGFloat position = [control orientation] == PSMTabBarHorizontalOrientation ?[[control style] leftMarginForTabBarControl] :[[control style] topMarginForTabBarControl]; + + // identify target cell + // mouse at beginning of tabs + NSPoint mouseLoc = [self currentMouseLoc]; + if([self destinationTabBar] == control) { + removeFlag = NO; + if(mouseLoc.x < [[control style] leftMarginForTabBarControl]) { + [self setTargetCell:[cells objectAtIndex:0]]; + } else { NSRect overCellRect; PSMTabBarCell *overCell = [control cellForPoint:mouseLoc cellFrame:&overCellRect]; - if (overCell) { + if(overCell) { // mouse among cells - placeholder - if ([overCell isPlaceholder]) { + if([overCell isPlaceholder]) { [self setTargetCell:overCell]; - } else if ([control orientation] == PSMTabBarHorizontalOrientation) { + } else if([control orientation] == PSMTabBarHorizontalOrientation) { // non-placeholders - horizontal orientation - if (mouseLoc.x < (overCellRect.origin.x + (overCellRect.size.width / 2.0))) { + if(mouseLoc.x < (overCellRect.origin.x + (overCellRect.size.width / 2.0))) { // mouse on left side of cell [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]]; } else { @@ -719,7 +685,7 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; } } else { // non-placeholders - vertical orientation - if (mouseLoc.y < (overCellRect.origin.y + (overCellRect.size.height / 2.0))) { + if(mouseLoc.y < (overCellRect.origin.y + (overCellRect.size.height / 2.0))) { // mouse on top of cell [self setTargetCell:[cells objectAtIndex:([cells indexOfObject:overCell] - 1)]]; } else { @@ -732,140 +698,137 @@ static PSMTabDragAssistant *sharedDragAssistant = nil; [self setTargetCell:[control lastVisibleTab]]; } } - } else { - [self setTargetCell:nil]; - } - - for (i = 0; i < cellCount; i++) { - PSMTabBarCell *cell = [cells objectAtIndex:i]; - NSRect newRect = [cell frame]; - if (![cell isInOverflowMenu]) { - if ([cell isPlaceholder]) { - if (cell == [self targetCell]) { - [cell setCurrentStep:([cell currentStep] + 1)]; - } else { - [cell setCurrentStep:([cell currentStep] - 1)]; - if ([cell currentStep] > 0) { - removeFlag = NO; - } - } - - if ([control orientation] == PSMTabBarHorizontalOrientation) { + } else { + [self setTargetCell:nil]; + } + + for(i = 0; i < cellCount; i++) { + PSMTabBarCell *cell = [cells objectAtIndex:i]; + NSRect newRect = [cell frame]; + if(![cell isInOverflowMenu]) { + if([cell isPlaceholder]) { + if(cell == [self targetCell]) { + [cell setCurrentStep:([cell currentStep] + 1)]; + } else { + [cell setCurrentStep:([cell currentStep] - 1)]; + if([cell currentStep] > 0) { + removeFlag = NO; + } + } + + if([control orientation] == PSMTabBarHorizontalOrientation) { newRect.size.width = [[_sineCurveWidths objectAtIndex:[cell currentStep]] integerValue]; } else { newRect.size.height = [[_sineCurveWidths objectAtIndex:[cell currentStep]] integerValue]; } - } - } else { - break; - } - - if ([control orientation] == PSMTabBarHorizontalOrientation) { + } + } else { + break; + } + + if([control orientation] == PSMTabBarHorizontalOrientation) { newRect.origin.x = position; position += newRect.size.width; } else { newRect.origin.y = position; position += newRect.size.height; } - [cell setFrame:newRect]; - if ([cell indicator]) { - [[cell indicator] setFrame:[[control style] indicatorRectForTabCell:cell]]; - } - } - if (removeFlag) { - [_participatingTabBars removeObject:control]; - [self removeAllPlaceholdersFromTabBar:control]; - } + [cell setFrame:newRect]; + if([cell indicator]) { + [[cell indicator] setFrame:[[control style] indicatorRectForTabCell:cell]]; + } + } + if(removeFlag) { + [_participatingTabBars removeObject:control]; + [self removeAllPlaceholdersFromTabBar:control]; + } } #pragma mark - #pragma mark Placeholders -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control withDraggedCell:(PSMTabBarCell *)cell -{ - // called upon first drag - must distribute placeholders - [self distributePlaceholdersInTabBar:control]; - +- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control withDraggedCell:(PSMTabBarCell *)cell { + // called upon first drag - must distribute placeholders + [self distributePlaceholdersInTabBar:control]; + NSMutableArray *cells = [control cells]; - - // replace dragged cell with a placeholder, and clean up surrounding cells - NSInteger cellIndex = [cells indexOfObject:cell]; - PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:YES inControlView:control] autorelease]; - [cells replaceObjectAtIndex:cellIndex withObject:pc]; - [cells removeObjectAtIndex:(cellIndex + 1)]; - [cells removeObjectAtIndex:(cellIndex - 1)]; - - if (cellIndex - 2 >= 0) { + + // replace dragged cell with a placeholder, and clean up surrounding cells + NSInteger cellIndex = [cells indexOfObject:cell]; + PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:YES inControlView:control] autorelease]; + [cells replaceObjectAtIndex:cellIndex withObject:pc]; + [cells removeObjectAtIndex:(cellIndex + 1)]; + [cells removeObjectAtIndex:(cellIndex - 1)]; + + if(cellIndex - 2 >= 0) { pc = [cells objectAtIndex:cellIndex - 2]; [pc setTabState:~[pc tabState] & PSMTab_RightIsSelectedMask]; } } -- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control -{ - NSInteger i, numVisibleTabs = [control numberOfVisibleTabs]; - for (i = 0; i < numVisibleTabs; i++) { - PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control] autorelease]; - [[control cells] insertObject:pc atIndex:(2 * i)]; - } - +- (void)distributePlaceholdersInTabBar:(PSMTabBarControl *)control { + NSInteger i, numVisibleTabs = [control numberOfVisibleTabs]; + for(i = 0; i < numVisibleTabs; i++) { + PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control] autorelease]; + [[control cells] insertObject:pc atIndex:(2 * i)]; + } + PSMTabBarCell *pc = [[[PSMTabBarCell alloc] initPlaceholderWithFrame:[[self draggedCell] frame] expanded:NO inControlView:control] autorelease]; - if ([[control cells] count] > (2 * numVisibleTabs)) { + if([[control cells] count] > (2 * numVisibleTabs)) { [[control cells] insertObject:pc atIndex:(2 * numVisibleTabs)]; } else { [[control cells] addObject:pc]; } } -- (void)removeAllPlaceholdersFromTabBar:(PSMTabBarControl *)control -{ - NSInteger i, cellCount = [[control cells] count]; - for (i = (cellCount - 1); i >= 0; i--) { - PSMTabBarCell *cell = [[control cells] objectAtIndex:i]; - if ([cell isPlaceholder]) { +- (void)removeAllPlaceholdersFromTabBar:(PSMTabBarControl *)control { + NSInteger i, cellCount = [[control cells] count]; + for(i = (cellCount - 1); i >= 0; i--) { + PSMTabBarCell *cell = [[control cells] objectAtIndex:i]; + if([cell isPlaceholder]) { [control removeTabForCell:cell]; - } - } - // redraw - [control update:NO]; + } + } + // redraw + [control update:NO]; } #pragma mark - #pragma mark Archiving - (void)encodeWithCoder:(NSCoder *)aCoder { - //[super encodeWithCoder:aCoder]; - if ([aCoder allowsKeyedCoding]) { - [aCoder encodeObject:_sourceTabBar forKey:@"sourceTabBar"]; - [aCoder encodeObject:_destinationTabBar forKey:@"destinationTabBar"]; - [aCoder encodeObject:_participatingTabBars forKey:@"participatingTabBars"]; - [aCoder encodeObject:_draggedCell forKey:@"draggedCell"]; - [aCoder encodeInteger:_draggedCellIndex forKey:@"draggedCellIndex"]; - [aCoder encodeBool:_isDragging forKey:@"isDragging"]; - [aCoder encodeObject:_animationTimer forKey:@"animationTimer"]; - [aCoder encodeObject:_sineCurveWidths forKey:@"sineCurveWidths"]; - [aCoder encodePoint:_currentMouseLoc forKey:@"currentMouseLoc"]; - [aCoder encodeObject:_targetCell forKey:@"targetCell"]; - } + //[super encodeWithCoder:aCoder]; + if([aCoder allowsKeyedCoding]) { + [aCoder encodeObject:_sourceTabBar forKey:@"sourceTabBar"]; + [aCoder encodeObject:_destinationTabBar forKey:@"destinationTabBar"]; + [aCoder encodeObject:_participatingTabBars forKey:@"participatingTabBars"]; + [aCoder encodeObject:_draggedCell forKey:@"draggedCell"]; + [aCoder encodeInteger:_draggedCellIndex forKey:@"draggedCellIndex"]; + [aCoder encodeBool:_isDragging forKey:@"isDragging"]; + [aCoder encodeObject:_animationTimer forKey:@"animationTimer"]; + [aCoder encodeObject:_sineCurveWidths forKey:@"sineCurveWidths"]; + [aCoder encodePoint:_currentMouseLoc forKey:@"currentMouseLoc"]; + [aCoder encodeObject:_targetCell forKey:@"targetCell"]; + } } - (id)initWithCoder:(NSCoder *)aDecoder { - //self = [super initWithCoder:aDecoder]; - //if (self) { - if ([aDecoder allowsKeyedCoding]) { - _sourceTabBar = [[aDecoder decodeObjectForKey:@"sourceTabBar"] retain]; - _destinationTabBar = [[aDecoder decodeObjectForKey:@"destinationTabBar"] retain]; - _participatingTabBars = [[aDecoder decodeObjectForKey:@"participatingTabBars"] retain]; - _draggedCell = [[aDecoder decodeObjectForKey:@"draggedCell"] retain]; - _draggedCellIndex = [aDecoder decodeIntegerForKey:@"draggedCellIndex"]; - _isDragging = [aDecoder decodeBoolForKey:@"isDragging"]; - _animationTimer = [[aDecoder decodeObjectForKey:@"animationTimer"] retain]; - _sineCurveWidths = [[aDecoder decodeObjectForKey:@"sineCurveWidths"] retain]; - _currentMouseLoc = [aDecoder decodePointForKey:@"currentMouseLoc"]; - _targetCell = [[aDecoder decodeObjectForKey:@"targetCell"] retain]; - } - //} - return self; + //self = [super initWithCoder:aDecoder]; + //if (self) { + if([aDecoder allowsKeyedCoding]) { + _sourceTabBar = [[aDecoder decodeObjectForKey:@"sourceTabBar"] retain]; + _destinationTabBar = [[aDecoder decodeObjectForKey:@"destinationTabBar"] retain]; + _participatingTabBars = [[aDecoder decodeObjectForKey:@"participatingTabBars"] retain]; + _draggedCell = [[aDecoder decodeObjectForKey:@"draggedCell"] retain]; + _draggedCellIndex = [aDecoder decodeIntegerForKey:@"draggedCellIndex"]; + _isDragging = [aDecoder decodeBoolForKey:@"isDragging"]; + _animationTimer = [[aDecoder decodeObjectForKey:@"animationTimer"] retain]; + _sineCurveWidths = [[aDecoder decodeObjectForKey:@"sineCurveWidths"] retain]; + _currentMouseLoc = [aDecoder decodePointForKey:@"currentMouseLoc"]; + _targetCell = [[aDecoder decodeObjectForKey:@"targetCell"] retain]; + } + //} + return self; } diff --git a/cocoa/PSMTabBarControl/PSMTabDragView.h b/cocoa/PSMTabBarControl/PSMTabDragView.h index bdf73304b..f8018d290 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragView.h +++ b/cocoa/PSMTabBarControl/PSMTabDragView.h @@ -9,8 +9,9 @@ #import @interface PSMTabDragView : NSView { - NSImage *_image, *_alternateImage; - CGFloat _alpha; + NSImage *_image; + NSImage *_alternateImage; + CGFloat _alpha; } - (void)setFadeValue:(CGFloat)value; - (NSImage *)image; diff --git a/cocoa/PSMTabBarControl/PSMTabDragView.m b/cocoa/PSMTabBarControl/PSMTabDragView.m index 259116ae8..2c9781dbc 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragView.m +++ b/cocoa/PSMTabBarControl/PSMTabDragView.m @@ -12,14 +12,13 @@ @implementation PSMTabDragView - (id)initWithFrame:(NSRect)frame { - if ( (self = [super initWithFrame:frame]) ) { + if((self = [super initWithFrame:frame])) { _alpha = 1.0; - } - return self; + } + return self; } -- (void)dealloc -{ +- (void)dealloc { [_image release]; [_alternateImage release]; [super dealloc]; @@ -32,35 +31,30 @@ NSRect srcRect; srcRect.origin = NSZeroPoint; srcRect.size = [_image size]; - + [_image drawInRect:[self bounds] fromRect:srcRect operation:NSCompositeSourceOver fraction:primaryAlpha]; srcRect.size = [_alternateImage size]; [_alternateImage drawInRect:[self bounds] fromRect:srcRect operation:NSCompositeSourceOver fraction:alternateAlpha]; } -- (void)setFadeValue:(CGFloat)value -{ +- (void)setFadeValue:(CGFloat)value { _alpha = value; } -- (NSImage *)image -{ +- (NSImage *)image { return _image; } -- (void)setImage:(NSImage *)image -{ +- (void)setImage:(NSImage *)image { [_image release]; _image = [image retain]; } -- (NSImage *)alternateImage -{ +- (NSImage *)alternateImage { return _alternateImage; } -- (void)setAlternateImage:(NSImage *)image -{ +- (void)setAlternateImage:(NSImage *)image { [_alternateImage release]; _alternateImage = [image retain]; } diff --git a/cocoa/PSMTabBarControl/PSMTabDragWindow.h b/cocoa/PSMTabBarControl/PSMTabDragWindow.h index fd26e7496..04cde248c 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragWindow.h +++ b/cocoa/PSMTabBarControl/PSMTabDragWindow.h @@ -11,7 +11,7 @@ @class PSMTabDragView; @interface PSMTabDragWindow : NSWindow { - PSMTabDragView *_dragView; + PSMTabDragView *_dragView; } + (PSMTabDragWindow *)dragWindowWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask; diff --git a/cocoa/PSMTabBarControl/PSMTabDragWindow.m b/cocoa/PSMTabBarControl/PSMTabDragWindow.m index 0d07c432d..d6fcc95a3 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragWindow.m +++ b/cocoa/PSMTabBarControl/PSMTabDragWindow.m @@ -11,40 +11,37 @@ @implementation PSMTabDragWindow -+ (PSMTabDragWindow *)dragWindowWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask -{ ++ (PSMTabDragWindow *)dragWindowWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask { return [[[PSMTabDragWindow alloc] initWithImage:image styleMask:styleMask] autorelease]; } -- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask -{ +- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask { NSSize size = [image size]; - - if ( (self = [super initWithContentRect:NSMakeRect(0, 0, size.width, size.height) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO]) ) { + + if((self = [super initWithContentRect:NSMakeRect(0, 0, size.width, size.height) styleMask:styleMask backing:NSBackingStoreBuffered defer:NO])) { _dragView = [[[PSMTabDragView alloc] initWithFrame:NSMakeRect(0, 0, size.width, size.height)] autorelease]; [self setContentView:_dragView]; [self setLevel:NSStatusWindowLevel]; [self setIgnoresMouseEvents:YES]; [self setOpaque:NO]; - + [_dragView setImage:image]; - + //Set the size of the window to be the exact size of the drag image NSRect windowFrame = [self frame]; windowFrame.origin.y += windowFrame.size.height - size.height; windowFrame.size = size; - - if (styleMask | NSBorderlessWindowMask) { + + if(styleMask | NSBorderlessWindowMask) { windowFrame.size.height += 22; } - + [self setFrame:windowFrame display:YES]; } return self; } -- (PSMTabDragView *)dragView -{ +- (PSMTabDragView *)dragView { return _dragView; } diff --git a/cocoa/PSMTabBarControl/PSMTabDragWindowController.h b/cocoa/PSMTabBarControl/PSMTabDragWindowController.h index 1727d8b84..5948207f2 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragWindowController.h +++ b/cocoa/PSMTabBarControl/PSMTabDragWindowController.h @@ -15,15 +15,15 @@ @class PSMTabDragView; @interface PSMTabDragWindowController : NSWindowController { - PSMTabBarTearOffStyle _tearOffStyle; - PSMTabDragView *_view; - NSAnimation *_animation; - NSTimer *_timer; - - BOOL _showingAlternate; - NSRect _originalWindowFrame; + PSMTabBarTearOffStyle _tearOffStyle; + PSMTabDragView *_view; + NSAnimation *_animation; + NSTimer *_timer; + + BOOL _showingAlternate; + NSRect _originalWindowFrame; } -- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; +- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger) styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle; - (NSImage *)image; - (NSImage *)alternateImage; diff --git a/cocoa/PSMTabBarControl/PSMTabDragWindowController.m b/cocoa/PSMTabBarControl/PSMTabDragWindowController.m index 018bca172..3a6e8c663 100644 --- a/cocoa/PSMTabBarControl/PSMTabDragWindowController.m +++ b/cocoa/PSMTabBarControl/PSMTabDragWindowController.m @@ -12,104 +12,96 @@ @implementation PSMTabDragWindowController -- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle -{ +- (id)initWithImage:(NSImage *)image styleMask:(NSUInteger)styleMask tearOffStyle:(PSMTabBarTearOffStyle)tearOffStyle { PSMTabDragWindow *window = [PSMTabDragWindow dragWindowWithImage:image styleMask:styleMask]; - if ( (self = [super initWithWindow:window]) ) { + if((self = [super initWithWindow:window])) { _view = [[window dragView] retain]; _tearOffStyle = tearOffStyle; - - if (tearOffStyle == PSMTabBarTearOffMiniwindow) { + + if(tearOffStyle == PSMTabBarTearOffMiniwindow) { [window setBackgroundColor:[NSColor clearColor]]; [window setHasShadow:YES]; } - + [window setAlphaValue:kPSMTabDragWindowAlpha]; } return self; } -- (void)dealloc -{ - if (_timer) { +- (void)dealloc { + if(_timer) { [_timer invalidate]; } - - if (_animation) { + + if(_animation) { [_animation release]; } - + [_view release]; [super dealloc]; } -- (NSImage *)image -{ +- (NSImage *)image { return [_view image]; } -- (NSImage *)alternateImage -{ +- (NSImage *)alternateImage { return [_view alternateImage]; } -- (void)setAlternateImage:(NSImage *)image -{ +- (void)setAlternateImage:(NSImage *)image { [_view setAlternateImage:image]; } -- (BOOL)isAnimating -{ +- (BOOL)isAnimating { return _animation != nil; } -- (void)switchImages -{ - if (_tearOffStyle != PSMTabBarTearOffMiniwindow || ![_view alternateImage]) { +- (void)switchImages { + if(_tearOffStyle != PSMTabBarTearOffMiniwindow || ![_view alternateImage]) { return; } - + CGFloat progress = 0; _showingAlternate = !_showingAlternate; - - if (_animation) { + + if(_animation) { //An animation already exists, get the current progress progress = 1.0f - [_animation currentProgress]; [_animation stopAnimation]; [_animation release]; } - + //begin animating _animation = [[NSAnimation alloc] initWithDuration:0.25 animationCurve:NSAnimationEaseInOut]; [_animation setAnimationBlockingMode:NSAnimationNonblocking]; [_animation setCurrentProgress:progress]; [_animation startAnimation]; - + _originalWindowFrame = [[self window] frame]; - - if (_timer) { + + if(_timer) { [_timer invalidate]; } _timer = [NSTimer scheduledTimerWithTimeInterval:1.0f / 30.0f target:self selector:@selector(animateTimer:) userInfo:nil repeats:YES]; } -- (void)animateTimer:(NSTimer *)timer -{ +- (void)animateTimer:(NSTimer *)timer { NSRect frame = _originalWindowFrame; - NSImage *currentImage = _showingAlternate ? [_view alternateImage] : [_view image]; + NSImage *currentImage = _showingAlternate ?[_view alternateImage] :[_view image]; NSSize size = [currentImage size]; NSPoint mousePoint = [NSEvent mouseLocation]; CGFloat animationValue = [_animation currentValue]; - + frame.size.width = _originalWindowFrame.size.width + (size.width - _originalWindowFrame.size.width) * animationValue; frame.size.height = _originalWindowFrame.size.height + (size.height - _originalWindowFrame.size.height) * animationValue; frame.origin.x = mousePoint.x - (frame.size.width / 2); frame.origin.y = mousePoint.y - (frame.size.height / 2); - + [_view setFadeValue:_showingAlternate ? 1.0f - animationValue : animationValue]; [[self window] setFrame:frame display:YES]; - - if (![_animation isAnimating]) { + + if(![_animation isAnimating]) { [_animation release], _animation = nil; [timer invalidate]; _timer = nil; diff --git a/cocoa/PSMTabBarControl/PSMTabStyle.h b/cocoa/PSMTabBarControl/PSMTabStyle.h index 23c826fa6..ca3717435 100644 --- a/cocoa/PSMTabBarControl/PSMTabStyle.h +++ b/cocoa/PSMTabBarControl/PSMTabStyle.h @@ -6,9 +6,9 @@ // Copyright 2006 Positive Spin Media. All rights reserved. // -/* -Protocol to be observed by all style delegate objects. These objects handle the drawing responsibilities for PSMTabBarCell; once the control has been assigned a style, the background and cells draw consistent with that style. Design pattern and implementation by David Smith, Seth Willits, and Chris Forsythe, all touch up and errors by John P. :-) -*/ +/* + Protocol to be observed by all style delegate objects. These objects handle the drawing responsibilities for PSMTabBarCell; once the control has been assigned a style, the background and cells draw consistent with that style. Design pattern and implementation by David Smith, Seth Willits, and Chris Forsythe, all touch up and errors by John P. :-) + */ #import "PSMTabBarCell.h" #import "PSMTabBarControl.h" diff --git a/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h b/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h index d44bbcdc6..20202536a 100644 --- a/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h +++ b/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.h @@ -9,22 +9,21 @@ #import #import "PSMTabStyle.h" -@interface PSMUnifiedTabStyle : NSObject -{ - NSImage *unifiedCloseButton; - NSImage *unifiedCloseButtonDown; - NSImage *unifiedCloseButtonOver; - NSImage *unifiedCloseDirtyButton; - NSImage *unifiedCloseDirtyButtonDown; - NSImage *unifiedCloseDirtyButtonOver; - NSImage *_addTabButtonImage; - NSImage *_addTabButtonPressedImage; - NSImage *_addTabButtonRolloverImage; - - NSDictionary *_objectCountStringAttributes; - - CGFloat leftMargin; - PSMTabBarControl *tabBar; +@interface PSMUnifiedTabStyle : NSObject { + 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/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m b/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m index b9d8e56fc..77be601be 100644 --- a/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m +++ b/cocoa/PSMTabBarControl/PSMUnifiedTabStyle.m @@ -20,580 +20,554 @@ @implementation PSMUnifiedTabStyle -- (NSString *)name -{ - return @"Unified"; +- (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]; - +- (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; + 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]; +- (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 -{ +- (void)setLeftMarginForTabBarControl:(CGFloat)margin { leftMargin = margin; } -- (CGFloat)leftMarginForTabBarControl -{ - return leftMargin; +- (CGFloat)leftMarginForTabBarControl { + return leftMargin; } -- (CGFloat)rightMarginForTabBarControl -{ - return 24.0f; +- (CGFloat)rightMarginForTabBarControl { + return 24.0f; } -- (CGFloat)topMarginForTabBarControl -{ +- (CGFloat)topMarginForTabBarControl { return 10.0f; } -- (void)setOrientation:(PSMTabBarOrientation)value -{ - +- (void)setOrientation:(PSMTabBarOrientation)value { } #pragma mark - #pragma mark Add Tab Button -- (NSImage *)addTabButtonImage -{ - return _addTabButtonImage; +- (NSImage *)addTabButtonImage { + return _addTabButtonImage; } -- (NSImage *)addTabButtonPressedImage -{ - return _addTabButtonPressedImage; +- (NSImage *)addTabButtonPressedImage { + return _addTabButtonPressedImage; } -- (NSImage *)addTabButtonRolloverImage -{ - return _addTabButtonRolloverImage; +- (NSImage *)addTabButtonRolloverImage { + return _addTabButtonRolloverImage; } #pragma mark - #pragma mark Cell Specific -- (NSRect)dragRectForTabCell:(PSMTabBarCell *)cell orientation:(PSMTabBarOrientation)orientation -{ +- (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)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)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)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; +- (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)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)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 -{ +- (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 *)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; +- (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]; - +- (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) { + 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 + + 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) { + 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]) { + 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]]; + 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]]; + 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; - + [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]; - + 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)) { + 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)]; + [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) - { + 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)]; + [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)]; + [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]]; + + [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; +- (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.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]; + + 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]; + [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 -{ +- (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]]; + 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]) { + 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 -{ +- (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]; - } - } -} + + // 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"]; - } +- (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 = [super initWithCoder:aDecoder]; - //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; +- (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]; + 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 -- cgit v1.2.3