Adding support for menu providers to ITStatusItem using NSProxy subclass.
[ITKit.git] / ITStatusItem.m
1 #import "ITStatusItem.h"
2
3 @interface ITStatusItemMenuProxy : NSProxy {
4         id <ITStatusItemMenuProvider> menuProvider;
5         ITStatusItem *statusItem;
6 }
7
8 - (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item;
9
10 @end
11
12 @implementation ITStatusItemMenuProxy
13
14 + (BOOL)respondsToSelector:(SEL)aSelector {
15         if (![super respondsToSelector:aSelector]) {
16                 return [NSMenu respondsToSelector:aSelector];
17         }
18         return YES;
19 }
20
21 - (id)initWithMenuProvider:(id <ITStatusItemMenuProvider>)provider statusItem:(ITStatusItem *)item {
22         menuProvider = [provider retain];
23         statusItem = [item retain];
24         return self;
25 }
26
27 - (void)forwardInvocation:(NSInvocation *)anInvocation {
28         NSMenu *temporaryMenu = [[menuProvider menuForStatusItem:statusItem] retain];
29         [anInvocation setTarget:temporaryMenu];
30         [anInvocation invoke];
31         [temporaryMenu release];
32 }
33
34 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
35         NSMenu *temporaryMenu = [[menuProvider menuForStatusItem:statusItem] retain];
36         NSMethodSignature *signature = [temporaryMenu methodSignatureForSelector:aSelector];
37         [temporaryMenu release];
38         return signature;
39 }
40
41 - (void)dealloc {
42         [statusItem release];
43         [menuProvider release];
44         [super dealloc];
45 }
46
47 @end
48
49 @class NSStatusBarButton;
50
51 @interface NSStatusItem (ITStatusItemHacks)
52 - (id)_initInStatusBar:(NSStatusBar *)statusBar withLength:(float)length withPriority:(int)priority;
53 - (NSStatusBarButton *)_button;
54 @end
55
56 @protocol _ITStatusItemNSStatusItemPantherCompatability
57 - (void)setAlternateImage:(NSImage *)image;
58 - (NSImage *)alternateImage;
59 @end
60
61 @implementation ITStatusItem
62
63 static BOOL _ITStatusItemShouldKillShadow = NO;
64
65 + (void)initialize {
66         if ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_1) && (floor(NSAppKitVersionNumber) <= 663.6)) {
67                 _ITStatusItemShouldKillShadow = YES;
68         }
69 }
70
71 - (id)initWithStatusBar:(NSStatusBar *)statusBar withLength:(float)length {
72         return [self _initInStatusBar:statusBar withLength:length withPriority:1000];
73 }
74
75 - (id)_initInStatusBar:(NSStatusBar *)statusBar withLength:(float)length withPriority:(int)priority {
76         if ((self = [super _initInStatusBar:statusBar withLength:length withPriority:priority])) {
77                 if (_ITStatusItemShouldKillShadow) {
78                         [[(NSButton *)[self _button] cell] setType:NSNullCellType];
79                 }
80             [self setHighlightMode:YES];
81         }
82         return self;
83 }
84
85 - (NSImage *)alternateImage {
86         if ([super respondsToSelector:@selector(alternateImage)]) {
87                 return [(id <_ITStatusItemNSStatusItemPantherCompatability>)super alternateImage];
88         }
89         return [(NSButton *)[self _button] alternateImage];
90 }
91
92 - (void)setAlternateImage:(NSImage*)image {
93         if ([super respondsToSelector:@selector(setAlternateImage:)]) {
94                 [(id <_ITStatusItemNSStatusItemPantherCompatability>)super setAlternateImage:image];
95                 return;
96         }
97         [(NSButton *)[self _button] setAlternateImage:image];
98 }
99
100 - (id <ITStatusItemMenuProvider>)menuProvider {
101         return _menuProvider;
102 }
103
104 - (void)setMenuProvider:(id <ITStatusItemMenuProvider>)provider {
105         [_menuProvider autorelease];
106         _menuProvider = [provider retain];
107         if (provider) {
108                 [self setMenu:[[ITStatusItemMenuProxy alloc] initWithMenuProvider:_menuProvider statusItem:self]];
109         } else {
110                 [self setMenu:nil];
111         }
112 }
113
114 @end