summaryrefslogtreecommitdiff
path: root/frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m')
-rw-r--r--frontends/cocoa/PSMTabBarControl/PSMOverflowPopUpButton.m152
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