I'm playing around with an idea and basically I want a NSStatusItem with a NSPopoverController. I read about all the problem people had but I just want to try it. Is there a clean way to do it by now? All the versions I've seen are at least 1 year old and suuuuper hacky.
This was my approach so far but if I click my app in the statusbar nothing happens...
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
//[self.statusItem setView:view];
[self.statusItem setTitle:@"Test"];
[self.statusItem setHighlightMode:YES];
[self.statusItem setAction:@selector(activatePopover:)];
}
-(IBAction)activatePopover:(id)sender
{
BOOL isEnabled = NO;
if (isEnabled) {
[self.popover showRelativeToRect:NSMakeRect(0, 0, 50, 50) ofView:statusItem.view preferredEdge:NSMinYEdge];
} else {
[self.popover close];
}
}
Any ideas how to get this running?
Thanks
This will not work without using a custom view on the status item. If you don't set a custom view, the view
property will be empty (it only returns custom views, not whatever view NSStatusItem
uses internally when you just use setTitle
).
Unfortunately, as per Apple's docs, you'll need to provide your own view and handle clicks yourself if you want to use NSPopover
.
I haven't seen a complete example that encompasses correct handling of this (the default implementation of status items does rather a lot which you will have to do all manually), and also fixes popover wonkynesses:
NSPopover
, by default, won't become the key window (some controls won't work), unless you overwrite canBecomeKeyWindow
of NSPopover's windowpopUpStatusItemMenu
with an empty menu to correctly focus your status item)drawStatusBarBackgroundInRect
NSRunningApplication.currentApplication.activateWithOptions
to make sure all windows of your status item become active (otherwise your popover will, erratically, not be the receiver of keyboard input)NSEvent.addGlobalMonitorForEventsMatchingMask
(the built-in dismissal mechanism popovers come with doesn't work with status items)NSStatusBar.systemStatusBar.removeStatusItem
I hope to have a blog post about this out sometime soon (note: I'm using RubyMotion, not Objective-C), that explains all these issues and hopefully provides an easier base to create menulets. I'll update this comment if I write that post.
Code:
-(void)initializeStatusBarItem
{
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
NSImage* image = [NSImage imageNamed:@"image"];
// [image setTemplate:YES];
self.statusItem.button.image = image;
self.statusItem.highlightMode = NO;
self.statusItem.button.action = @selector(statusBarItemDidClick:);
}
- (void)statusBarItemDidClick:(NSStatusBarButton *)sender{
MainViewController *mainView = [[MainViewController alloc] init];
self.popoverView = [[NSPopover alloc] init];
[self.popoverView setContentViewController:mainView];
self.popoverView.contentSize = CGSizeMake(300, 400);
self.popoverView.behavior = NSPopoverBehaviorTransient;
[self.popoverView showRelativeToRect:sender.bounds ofView:sender preferredEdge:NSMaxYEdge];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With