I'm trying to make a simple menu bar only application on xcode 4. Everything actually works, but what I don't understand is that the icon is appearing twice in the menubar. One of the two icons actually works and gives the drop down menu with the working buttons, the other just changes to the highlighted icon images while clicked and goes back when released, without doing anything, not even the drop down menu appears.
This is the code I found and tested out:
- (void) awakeFromNib{
//Create the NSStatusBar and set its length
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
//Used to detect where the files are
NSBundle *bundle = [NSBundle mainBundle];
//Allocates and loads the images into the application which will be used for the NSStatusItem
statusImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:#"icon" ofType:#"png"]];
statusHighlightImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:#"icon-alt" ofType:#"png"]];
//Sets the images in the NSStatusItem
[statusItem setImage:statusImage];
[statusItem setAlternateImage:statusHighlightImage];
//Tells the NSStatusItem what menu to load
[statusItem setMenu:statusMenu];
//Sets the mouse over text
[statusItem setToolTip:#"My Custom Menu Item"];
//Enables highlighting
[statusItem setHighlightMode:YES];
then release the images
- (void) dealloc {
//Releases the 2 images we loaded into memory
[statusImage release];
[statusHighlightImage release];
[super dealloc];
and the header file:
#interface MenuletApp : NSObject <NSApplicationDelegate> {
NSWindow *window;
IBOutlet NSMenu *statusMenu;
NSStatusItem *statusItem;
NSImage *statusImage;
NSImage *statusHighlightImage;
with an IBAction to log Hello World when one of the items is clicked, and to terminate when the other is clicked.
I used a tutorial meant for XCode 3, so it might be that one of the steps is done differently, but looking at the code I have no idea where the second status item is getting created.
Thanks for the help.
Is it possible that -awakeFromNib is getting called twice? (Try putting a log message in there). Perhaps you have two objects of this class in your xib file?
Also, I'd recommend moving this to -applicationDidFinishLaunching:.
Related
I wanted to drop files in status bar app icon, so I've found implementation code that allows use NSView as NSStatusItem.
I'm trying to set image directly to view, but nothing happens I still getting empty status bar item. The menu works fine, just can't set the icon image.
NSImageView *imageView = [[NSImageView alloc] init];
[imageView setImage:[NSImage imageNamed:#"static.png"]];
[self addSubview:imageView];
I would like to create a status bar application which has non-menu style. same as FaceTab for facebook (I mean only interface, not functional)... this is my codes:
-(void)awakeFromNib{
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setView:customView];
//[statusItem setMenu:menu];
[statusItem setTitle:#"Status"];
[statusItem setHighlightMode:YES];
}
.....
so once I Use NSMenu everything works fine but when I use NSView and CustomView outlet nothing appear on menu bar. Help plz!
There are several moving parts involved, so the best advice I can give is to check out this excellent example project from Vadim Shpakovski.
At the end of your awakeFromNib method, you may need to call retain on the statusItem so that it doesn't go out of scope. I was struggling with this same problem, and adding [statusItem retain]; fixed it so that I now see my Status menu in the Mac OS status bar.
-(void)awakeFromNib{
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setView:customView];
// in my code, this is uncommented, and menu is an instance variable.
//[statusItem setMenu:menu];
[statusItem setTitle:#"Status"];
[statusItem setHighlightMode:YES];
// this was needed to get the icon to display in the status bar.
[statusItem retain];
}
I created a menu resource in a separate xib file, made it to be a subclass NSMenu like the following, and the file's owner to be the StatusMenu
#interface StatusMenu : NSMenu
{
#private
IBOutlet NSMenuItem *menuitem1;
IBOutlet NSMenuItem *menuitem2;
}
- (IBAction)action1:(id)sender;
- (IBAction)action2:(id)sender;
- (void)show;
#end
where show method is implemented in the following way
- (void)show
{
NSImage *menuImage = [[NSImage alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:#"myicon" ofType:#"png"]];
statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain];
[statusItem setImage:menuImage];
[statusItem setMenu:self];
[statusItem setHighlightMode:YES];
}
Then I created and launched the StatusMenu instance in the app delegate like the following
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
statusMenu = [[StatusMenu alloc] init];
statusMenu.user = self.user;
[statusMenu show];
}
Now, I can see the icon on the status bar. But when I click on the icon, no responding is happening. What could be wrong?
You don't usually subclass NSMenu to do what you're trying to do.
You can simply create another class (call It MenuController or something), put It in your storyboard/xib and have an outlet to It in your AppDelegate.
Here`s a sample project for you to check out.
I'm working on NSStatusItem. I've managed to use the setImage and setAlternateImage to work.
When user selects something, it takes a while for it to accomplish whatever it is doing. While it is doing something, I tried changing from the usual Image to a spinner. The way that I am doing it now is that I created a view, set the NSProgressIndicator to it, and then use
[statusItem setView: viewWithSpinner];
It seems to work until I try to remove it and display the original image. The only way I can hide it is to do
[statusItem setView: nil];
but that breaks everything, the original images don't come back. I guess cause there's no more view. I can't seem to save the original view before setting the viewWithSpinner.
Can someone advise me of a way of accomplishing this?
So...
NSStatusItem *myStatusItem;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[myStatusItem setImage:statusImage];
[myStatusItem setHighlightMode:YES];
[myStatusItem setAlternateImage:statusImageSel];
[myStatusItem setMenu:myStatusMenu];
etc...
[self createSpinner];
}
-(void)createSpinner
{
//to overcome the white border problem
NSView *progressIndicatorHolder = [[NSView alloc] init];
NSProgressIndicator *progressIndicator = [[NSProgressIndicator alloc] init];
[progressIndicator setBezeled: NO];
[progressIndicator setStyle: NSProgressIndicatorSpinningStyle];
[progressIndicator setControlSize: NSSmallControlSize];
[progressIndicator sizeToFit];
[progressIndicator setUsesThreadedAnimation:YES];
[progressIndicatorHolder addSubview:progressIndicator];
[progressIndicator startAnimation:self];
//for testing purposes
[[myStatusItem view] addSubview:progressIndicatorHolder];
spinnerView = progressIndicatorHolder;
}
I suggest save old view using [statusItem view] before setting to any other view. Before coming back to normal menu, set old saved view to statusItem using setView method.
If you're looking to just hide the NSStatusItem view, just call [yourStatusItem setLength:0].
I am a .Net developer that needs to port a small program over to Mac OS X. I have this mostly done (partly thanks to people on this site, thanks!) but have a bug that maybe people I can get help with.
I am creating a tool that sits in the status bar, that when clicked opens a window with several links or buttons. When the links or buttons are clicked they either open a website or external program. The problem is that the icon in the status bar disappears as I launch one of these external commands. Even more interesting is that the space on the status bar where the icon should be still responds; meaning that if I click on the area (even without the visible icon) it still runs the code and opens the window.
Here is the current code:
tray.m
#import "tray.h"
#import "MyView.h"
#implementation Tray
-(void) awakeFromNib{
NSBundle *bundle = [NSBundle mainBundle];
statusItem = [[NSImage alloc] initWithContentsofFile:[bundle pathForResource:"#icon" ofType:#"png"]];
MyView *view = [MyView new];
[statusItem setImage:statusImage];
view.image = statusImage;
[statusitem setView:view];
[statusitem setToolTip:#"Tray App"];
[view setTarget:self];
[view setAction:#selector(openWindow)];
}
-(IBAction)openWindow:(id)sender{
[trayWin makeKeyAndOrderFront:nil];
}
-(IBAction)openActMon:(id)sender {
(void)system("open '\/Applications/Utilities/Activity Monitor.app'");
}
tray.h
#import "MyView.h"
#interface Tray : NSObject {
NSStatusItem *statusItem;
NSImage *statusImage;
IBOutlet NSWindow * trayWin;
IBOutlet NSButton *ActMon;
void *openWindow;
}
#property (retain,nonatomic) NSStatusItem *statusItem;
-(IBAction)ActMon:(id)sender;
#end
MyView.h
#interface MyView : NSControl {
NSImage *image;
id target;
SEL action;
}
#property (retain)NSImage *image;
#property (assign) id target;
#property (assign) SEL action;
#end
MyView.m
#import "MyView.h"
#implementation MyView;
#synthethize image, target, action;
-(void)mousemouseUP:(NSEvent *)event{
[NSApp sendAction:selfself.action to:self.target from:self];
}
-(void)dealloc {
self.image = nil;
[super dealloc];
}
-(void)drawRect:(NSRect)rect {
[self.image drawInRect:CGRectMake(0,0,18,18) fromRect:NSZeroRect operation:NSCompositeSourceOver];
}
#end
}
The openActMon is run when the image/button is clicked, the image is located in the trayWin Window that is opened when the icon is clicked. At this point, Activity monitor successfully launches, but the icon in the StatusBar disappears.
I have tried putting a [super setNeedsDisplay:YES] in the openActMon, but that didn't help. And I added [view setNeedsDisplay:YES] in the openActMon and it responded undeclared.
I have given all of this code because, as I said, I am not a Objective-C coder, but .Net who just needs to port something small over. Hoping that this will be helpful to others in the future. Alot of this I have hodgepodged together from different forums and sites or have gotten from some help on StackOverflow. I am hoping someone can help.
Thanks in advance!
In awakeFromNib add:
[statusitem retain];
In awakeFromNib, you are allocating the NSImage into statusItem. I think you mean to allocate it into statusImage.