X-Git-Url: http://git.ithinksw.org/ITKit.git/blobdiff_plain/3263678eef57c78d7017185eaa2efb9e644c7f29..11c398c047d4e737a59c70f13de3cde3a788810a:/ITStatusItem.m?ds=sidebyside diff --git a/ITStatusItem.m b/ITStatusItem.m index 561ecf2..fade99c 100644 --- a/ITStatusItem.m +++ b/ITStatusItem.m @@ -1,4 +1,59 @@ #import "ITStatusItem.h" +#import + +@interface ITStatusItemMenuProxy : NSProxy { + id menuProvider; + ITStatusItem *statusItem; + AbsoluteTime cachedTime; + NSMenu *menu; +} + +- (id)initWithMenuProvider:(id )provider statusItem:(ITStatusItem *)item; + +@end + +@implementation ITStatusItemMenuProxy + ++ (BOOL)respondsToSelector:(SEL)aSelector { + if (![super respondsToSelector:aSelector]) { + return [NSMenu respondsToSelector:aSelector]; + } + return YES; +} + +- (id)initWithMenuProvider:(id )provider statusItem:(ITStatusItem *)item { + menuProvider = [provider retain]; + statusItem = [item retain]; + cachedTime = UpTime(); + menu = nil; + return self; +} + +- (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]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { + return [NSMenu instanceMethodSignatureForSelector:aSelector]; +} + +- (void)dealloc { + [menu release]; + [statusItem release]; + [menuProvider release]; + [super dealloc]; +} + +@end @class NSStatusBarButton; @@ -7,6 +62,11 @@ - (NSStatusBarButton *)_button; @end +@protocol _ITStatusItemNSStatusBarButtonMethods +- (NSMenu *)statusMenu; +- (void)setStatusMenu:(NSMenu *)menu; +@end + @protocol _ITStatusItemNSStatusItemPantherCompatability - (void)setAlternateImage:(NSImage *)image; - (NSImage *)alternateImage; @@ -28,6 +88,8 @@ static BOOL _ITStatusItemShouldKillShadow = NO; - (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]; } @@ -38,14 +100,14 @@ static BOOL _ITStatusItemShouldKillShadow = NO; - (NSImage *)alternateImage { if ([super respondsToSelector:@selector(alternateImage)]) { - return [(id <_ITStatusItemNSStatusItemPantherCompatability>)super alternateImage]; + return [super alternateImage]; } return [(NSButton *)[self _button] alternateImage]; } - (void)setAlternateImage:(NSImage*)image { if ([super respondsToSelector:@selector(setAlternateImage:)]) { - [(id <_ITStatusItemNSStatusItemPantherCompatability>)super setAlternateImage:image]; + [super setAlternateImage:image]; return; } [(NSButton *)[self _button] setAlternateImage:image]; @@ -56,16 +118,20 @@ static BOOL _ITStatusItemShouldKillShadow = NO; } - (void)setMenuProvider:(id )provider { - [_menuProvider autorelease]; - _menuProvider = [provider retain]; -} - -- (NSMenu *)menu { + [_menuProxy autorelease]; + _menuProxy = nil; + _menuProvider = provider; if (_menuProvider) { - return [_menuProvider menuForStatusItem:self]; + _menuProxy = [[ITStatusItemMenuProxy alloc] initWithMenuProvider:_menuProvider statusItem:self]; + [(id <_ITStatusItemNSStatusBarButtonMethods>)[self _button] setStatusMenu:_menuProxy]; } else { - return [super menu]; + [self setMenu:[self menu]]; } } +- (void)dealloc { + [_menuProxy release]; + [super dealloc]; +} + @end \ No newline at end of file