-//
-// ITStatusItem.m
-// iThinkAppKit
-//
-// Created by Joseph Spiros on Fri Dec 06 2002.
-// Copyright (c) 2002 iThink Software. All rights reserved.
-//
-
#import "ITStatusItem.h"
+#import <CoreServices/CoreServices.h>
+@interface ITStatusItemMenuProxy : NSProxy {
+ id <ITStatusItemMenuProvider> menuProvider;
+ ITStatusItem *statusItem;
+ AbsoluteTime cachedTime;
+ NSMenu *menu;
+}
-@implementation ITStatusItem
+- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item;
+
+@end
-- (id)initWithStatusBar:(NSStatusBar*)statusBar withLength:(float)length {
- statusItem = [statusBar statusItemWithLength:length];
+@implementation ITStatusItemMenuProxy
+
++ (BOOL)respondsToSelector:(SEL)aSelector {
+ if (![super respondsToSelector:aSelector]) {
+ return [NSMenu respondsToSelector:aSelector];
+ }
+ return YES;
+}
+
+- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item {
+ menuProvider = [provider retain];
+ statusItem = [item retain];
+ cachedTime = UpTime();
+ menu = nil;
+ return self;
}
-- (NSStatusItem*) statusItem {
- return statusItem;
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+ AbsoluteTime diff = SubAbsoluteFromAbsolute(UpTime(),cachedTime);
+
+ if (!menu || diff.lo > 1000000) {
+ [menu release];
+ menu = [[menuProvider menuForStatusItem:statusItem] retain];
+ cachedTime = UpTime();
+ }
+
+ [anInvocation setTarget:menu];
+ [anInvocation invoke];
}
-- (NSImage*) alternateImage {
- return [[statusItem _button] alternateImage];
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
+ return [NSMenu instanceMethodSignatureForSelector:aSelector];
}
-- (void) setAlternateImage:(NSImage*)image {
- if ([[[[statusItem _button] cell] super] type] != 0) {
- [[[statusItem _button] cell] setType:0];
- }
- [[statusItem _button] setAlternateImage:image];
+- (void)dealloc {
+ [menu release];
+ [statusItem release];
+ [menuProvider release];
+ [super dealloc];
}
@end
+
+@class NSStatusBarButton;
+
+@interface NSStatusItem (ITStatusItemHacks)
+- (id)_initInStatusBar:(NSStatusBar *)statusBar withLength:(float)length withPriority:(int)priority;
+- (NSStatusBarButton *)_button;
+@end
+
+@protocol _ITStatusItemNSStatusBarButtonMethods
+- (NSMenu *)statusMenu;
+- (void)setStatusMenu:(NSMenu *)menu;
+@end
+
+@protocol _ITStatusItemNSStatusItemPantherCompatability
+- (void)setAlternateImage:(NSImage *)image;
+- (NSImage *)alternateImage;
+@end
+
+@implementation ITStatusItem
+
+static BOOL _ITStatusItemShouldKillShadow = NO;
+
++ (void)initialize {
+ if ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_1) && (floor(NSAppKitVersionNumber) <= 663.6)) {
+ _ITStatusItemShouldKillShadow = YES;
+ }
+}
+
+- (id)initWithStatusBar:(NSStatusBar *)statusBar withLength:(float)length {
+ return [self _initInStatusBar:statusBar withLength:length withPriority:1000];
+}
+
+- (id)_initInStatusBar:(NSStatusBar *)statusBar withLength:(float)length withPriority:(int)priority {
+ if ((self = [super _initInStatusBar:statusBar withLength:length withPriority:priority])) {
+ _menuProvider = nil;
+ _menuProxy = nil;
+ if (_ITStatusItemShouldKillShadow) {
+ [[(NSButton *)[self _button] cell] setType:NSNullCellType];
+ }
+ [self setHighlightMode:YES];
+ }
+ return self;
+}
+
+- (NSImage *)alternateImage {
+ if ([super respondsToSelector:@selector(alternateImage)]) {
+ return [super alternateImage];
+ }
+ return [(NSButton *)[self _button] alternateImage];
+}
+
+- (void)setAlternateImage:(NSImage*)image {
+ if ([super respondsToSelector:@selector(setAlternateImage:)]) {
+ [super setAlternateImage:image];
+ return;
+ }
+ [(NSButton *)[self _button] setAlternateImage:image];
+}
+
+- (id <ITStatusItemMenuProvider>)menuProvider {
+ return _menuProvider;
+}
+
+- (void)setMenuProvider:(id <ITStatusItemMenuProvider>)provider {
+ [_menuProxy autorelease];
+ _menuProxy = nil;
+ _menuProvider = provider;
+ if (_menuProvider) {
+ _menuProxy = [[ITStatusItemMenuProxy alloc] initWithMenuProvider:_menuProvider statusItem:self];
+ [(id <_ITStatusItemNSStatusBarButtonMethods>)[self _button] setStatusMenu:_menuProxy];
+ } else {
+ [self setMenu:[self menu]];
+ }
+}
+
+- (void)dealloc {
+ [_menuProxy release];
+ [super dealloc];
+}
+
+@end
\ No newline at end of file