Jay Taylor's notes
back to listing indexiOS and OS X Development: Cocoa Popup window in the Status bar
[web search]Developer or Designer? I have some nice Projects.
Maybe you have apps in the App Store? Try NativeConnect.
July 5, 2011
Cocoa Popup window in the Status bar
My CodeBox app for Mac OS X has got an embedded helper app named CodeBar. It is a small utility resided in the system status bar. In this blog post, I'm going to share an open-source project demonstrating how to implement a custom status icon with a popup window. I hope it will be useful for those who are new to Cocoa and want to make their own utility living in the status bar.
First, we have to allocate a new NSStatusItem to place it into the menu bar. This task is managed by the controller class named MenubarController. To make status item more flexible, we use a custom StatusItemView to display its contents in the menu bar. The demo project provides the simplest implementation that draws a Star icon in that view. You can have even more advanced icon by adding handling of drag & drop or any other feature supported by regular views.
Next, we need a customized window to display it as a popover. In the demo project, this window is a panel managed by the PanelController class. It loads the panel component from NIB and manages its live cycle. Also, it configures popover appearance by removing title bar and standard window background.
Finally, once we have menu bar icon and popover, it is time to connect them. The top level controller class ApplicationDelegate is watching for clicks in the menu bar and passes them to the panel controller. Then, after panel controller is closed, application delegate asks menu bar icon to remove a blue highlight.
Popup project on GitHub has got all source files that you need to build a demo app in Xcode 4.
P. S. In Lion, Apple is adding a new class for popovers like in iOS. So, after OS X 10.7 is released, you would better to rely on native Cocoa classes where it is possible. In other cases, the Popup project should still be usable.
Update: What a shame. It looks like implementation using NSPopover requires a lot of hacks. Please find more information here.
46 comments:
@Anonymous Could you please be more specific? What do you mean by “window move”? Thanks.
Reply- AnonymousAugust 11, 2011 at 5:21 PM
Nice example. But can you tell me please, what does
Reply
void *kContextActivePanel = &kContextActivePanel;
do? void *kContextActivePanel = &kContextActivePanel is another way to make a unique constant identifier kContextActivePanel for using in the key value observing.
Reply
Something like void *kContextActivePanel = @"ActivePanelContext" would work too.I'm wondering if there's any way you'd update your code to use the new NSPopOver class? (And, ARC/xcode 4.2 would be nice too ;) )
ReplyRepliesMaybe someday, when I have time :)
Please do that :) If I try to code this it always won't work :(
Or can you please make a video tutorial?
I think when you show us how to do that, it's easier to understand what we have to do.Please update for using ARC.
Also,
How can you add text next to the image in the menu bar?- AnonymousMay 7, 2012 at 7:46 PM
I understand the problem of time, but a step-by-step video tutorial with explanations would be a tremendous help for beginners!
- AnonymousFebruary 26, 2012 at 12:29 AM
Vadim,
Reply
I test your code, but I notice that when you open the panel, and don't click outside the window (panel), and click in other icon on the menubar, the panel don't close.
Do you know how to fix this?
Thanks.RepliesThanks for the heads up, I have just fixed it!
- AnonymousFebruary 27, 2012 at 1:07 AM
Without being annoying, on the first click the panel still does not close if you click on another icon from the menubar.
After you click out of the menu bar for a first time, it works correctly every time than, but before that the panel remains open, following a screenshot:
http://img826.imageshack.us/img826/8528/popupx.png That's because you run the app from Xcode. Try to launch it from Finder.
- AnonymousMarch 2, 2012 at 4:16 AM
You are right. I did not know this, thanks.
- AnonymousApril 8, 2012 at 6:05 PM
I have tried this in my own app, on Lion it all works fine.
Reply
However, there is an error, when the PanelController is calling it's window.
It seems to be a zombie. I use ARC btw.
I have no idea why this happens, when I convert the PanelProject right here to ARC, it works flawlessly.
Can anyone help me out?RepliesPlease create a new issue on the GitHub and describe step-by-step how to reproduce it. Thanks in advance!
- AnonymousJune 12, 2012 at 4:47 AM
Maybe you can advise how to include resize in your "popup" ? I founded solution to set window stylemask to NSResizableWindowMask, but i still can't hide title bar.(
ReplyRepliesI believe you cannot use a resizing behavior of a window because it is handled by the theme frame which requires a title bar. Sorry.
- AnonymousJune 16, 2012 at 11:19 PM
i did it) with custom resize rect and mouse event.
Congratulations, it must have been quite a tricky task :)
- AnonymousAugust 13, 2012 at 4:51 PM
anonymous june 16: it would be nice if you could share how you did the windows resize.
Reply
Vadim: thanks for sharing a great tutorial. For anyone using MonoMac, I've written a port here: http://dan.clarke.name/2012/08/cocoa-popup-window-in-the-status-bar-monomac-port/
Reply
Many thanks to Vadim for the initial solution!RepliesThanks Dan, it looks great!
Hey guys, this is an awesome template and I have been using it in two of my projects now!
Reply
Just wanted to know, if i want display the app on left click, and I want to display a menu on right click, what do I do?RepliesThanks for the feedback! I would try to override mouseDown: in StatusItemView.m and send different actions depending on the pressed mouse button. Sorry for the late reply :)
- AnonymousJuly 4, 2013 at 10:03 AM
Im trying to run it on MAC OS X 10.6 with Xcode 4
Reply
Although it is working fine on MAC OS 10.8 but having problem when I use it on MAC OS X 10.6. It's not running.. ?RepliesI have no 10.6 installed to test. Could you please be more specific? What kind of problem do you have exactly? Sorry for inconvenience.
Awesome stuff! It's great that you are still maintaining it after 2 years now! Kudos!
Reply- AnonymousJuly 31, 2013 at 6:45 PM
hi, your project helped me a lot in understanding how things are working!
Reply
I'm trying to understand how to close the panel only by clicking on status bar icon?
My app opens some "choose file" dialogs, so i have to click each time to reopen the panel..
hints? - AnonymousSeptember 24, 2013 at 8:34 AM
This is a great example of exactly what I was looking for. However, there was a question awhile back that asked something I wanted to know also:
Reply
"How can you add text next to the image in the menu bar?"
Can you please respond to this?
Thanks! Wasn't sure how to thank you for this, so I bought CodeBox. This can be my first snippet to save, thank you, thank you, thank you :)
ReplyRepliesThanks, thanks a lot! :)
- AnonymousJanuary 27, 2014 at 7:59 PM
Its a great code, however can you customize it load webview?
Reply Hi Vadim, how did you manage keeping the view acting like a float? I’m talking about the behavior in mission control, where it fades out when you enter mission control. other examples for popups (with NSPopover) all have that bug...
Reply
BTW I'm a fan of codebox and pngcompressor!
thx a lot for your great work...RepliesHi Seb, thanks a lot for your support. I am not sure what you mean by “float”. Maybe Utility window style is what you need? Sorry for the late reply.
This look beatiful! Has it yet - or du you have any plans to rewrite this in Swift?
ReplyRepliesThanks for the feedback!
No, sorry :) If you ever do this, please let me know, I would add the link to the article.
- Jonas FreyJanuary 23, 2015 at 5:34 PM
Really great project!
Reply
Thanks!
But a few comments in code would be really helpful, to understand everything...