I also had the ITStatusItem directly set the cell's menu, rather than setting itself's menu, this way, everything will work fine if you change your mind and decide to use setMenu: instead of setMenuProvider:.
@interface ITStatusItem : NSStatusItem {
id <ITStatusItemMenuProvider> _menuProvider;
@interface ITStatusItem : NSStatusItem {
id <ITStatusItemMenuProvider> _menuProvider;
}
- (id)initWithStatusBar:(NSStatusBar *)statusBar withLength:(float)length;
}
- (id)initWithStatusBar:(NSStatusBar *)statusBar withLength:(float)length;
+#import <CoreServices/CoreServices.h>
@interface ITStatusItemMenuProxy : NSProxy {
id <ITStatusItemMenuProvider> menuProvider;
ITStatusItem *statusItem;
@interface ITStatusItemMenuProxy : NSProxy {
id <ITStatusItemMenuProvider> menuProvider;
ITStatusItem *statusItem;
+ AbsoluteTime cachedTime;
+ NSMenu *menu;
}
- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item;
}
- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item;
- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item {
menuProvider = [provider retain];
statusItem = [item retain];
- (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item {
menuProvider = [provider retain];
statusItem = [item retain];
+ cachedTime = UpTime();
+ menu = nil;
return self;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
return self;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
- NSMenu *temporaryMenu = [[menuProvider menuForStatusItem:statusItem] retain];
- [anInvocation setTarget:temporaryMenu];
+ AbsoluteTime diff = SubAbsoluteFromAbsolute(UpTime(),cachedTime);
+
+ if (!menu || diff.lo > 1000000) {
+ [menu release];
+ menu = [[menuProvider menuForStatusItem:statusItem] retain];
+ cachedTime = UpTime();
+ }
+
+ [anInvocation setTarget:menu];
- [temporaryMenu release];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
- NSMenu *temporaryMenu = [[menuProvider menuForStatusItem:statusItem] retain];
- NSMethodSignature *signature = [temporaryMenu methodSignatureForSelector:aSelector];
- [temporaryMenu release];
- return signature;
+ return [NSMenu instanceMethodSignatureForSelector:aSelector];
[statusItem release];
[menuProvider release];
[super dealloc];
[statusItem release];
[menuProvider release];
[super dealloc];
- (NSStatusBarButton *)_button;
@end
- (NSStatusBarButton *)_button;
@end
+@protocol _ITStatusItemNSStatusBarButtonMethods
+- (NSMenu *)statusMenu;
+- (void)setStatusMenu:(NSMenu *)menu;
+@end
+
@protocol _ITStatusItemNSStatusItemPantherCompatability
- (void)setAlternateImage:(NSImage *)image;
- (NSImage *)alternateImage;
@protocol _ITStatusItemNSStatusItemPantherCompatability
- (void)setAlternateImage:(NSImage *)image;
- (NSImage *)alternateImage;
- (id)_initInStatusBar:(NSStatusBar *)statusBar withLength:(float)length withPriority:(int)priority {
if ((self = [super _initInStatusBar:statusBar withLength:length withPriority:priority])) {
- (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];
}
if (_ITStatusItemShouldKillShadow) {
[[(NSButton *)[self _button] cell] setType:NSNullCellType];
}
}
- (void)setMenuProvider:(id <ITStatusItemMenuProvider>)provider {
}
- (void)setMenuProvider:(id <ITStatusItemMenuProvider>)provider {
- [_menuProvider autorelease];
- _menuProvider = [provider retain];
- if (provider) {
- [self setMenu:[[ITStatusItemMenuProxy alloc] initWithMenuProvider:_menuProvider statusItem:self]];
+ [_menuProxy autorelease];
+ _menuProxy = nil;
+ _menuProvider = provider;
+ if (_menuProvider) {
+ _menuProxy = [[ITStatusItemMenuProxy alloc] initWithMenuProvider:_menuProvider statusItem:self];
+ [(id <_ITStatusItemNSStatusBarButtonMethods>)[self _button] setStatusMenu:_menuProxy];
+ [self setMenu:[self menu]];
+- (void)dealloc {
+ [_menuProxy release];
+ [super dealloc];
+}
+
@end
\ No newline at end of file
@end
\ No newline at end of file