diff options
Diffstat (limited to 'frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m')
-rw-r--r-- | frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m b/frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m new file mode 100644 index 000000000..c316f6973 --- /dev/null +++ b/frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m @@ -0,0 +1,152 @@ +// +// PSMOverflowPopUpButton.m +// PSMTabBarControl +// +// Created by John Pannell on 11/4/05. +// Copyright 2005 Positive Spin Media. All rights reserved. +// + +#import "PSMOverflowPopUpButton.h" +#import "PSMTabBarControl.h" + +#define TIMER_INTERVAL 1.0 / 15.0 +#define ANIMATION_STEP 0.033f + +@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"]]; + _PSMTabBarOverflowDownPopUpImage = [[NSImage alloc] initByReferencingFile:[[PSMTabBarControl bundle] pathForImageResource:@"overflowImagePressed"]]; + _animatingAlternateImage = NO; + } + return self; +} + +- (void)dealloc { + [_PSMTabBarOverflowPopUpImage release]; + [_PSMTabBarOverflowDownPopUpImage release]; + [super dealloc]; +} + +- (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) { + 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]) { + drawPoint.y += altImageSize.height; + } + + [[self alternateImage] compositeToPoint:drawPoint operation:NSCompositeSourceOver fraction:sin(_animationValue * M_PI)]; + } +} + +- (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) { + // Stop any animating alternate image if we hide + [_animationTimer invalidate], _animationTimer = nil; + } 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 { + _down = NO; + [self setNeedsDisplay:YES]; + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (void)setAnimatingAlternateImage:(BOOL)flag { + if(_animatingAlternateImage != flag) { + _animatingAlternateImage = 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; + } + + [self setNeedsDisplay:YES]; + } + } +} + +- (BOOL)animatingAlternateImage; +{ + return _animatingAlternateImage; +} + +- (void)animateStep:(NSTimer *)timer { + _animationValue += ANIMATION_STEP; + + if(_animationValue >= 1) { + _animationValue = ANIMATION_STEP; + } + + [self setNeedsDisplay:YES]; +} + +#pragma mark - +#pragma mark Archiving + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [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]; + [self setAnimatingAlternateImage:[aDecoder decodeBoolForKey:@"PSMTabBarOverflowAnimatingAlternateImage"]]; + } + } + return self; +} + +@end |