Icon in menubar - a working solution [NSStatusItem]

Hi all,

I’ve managed to get an icon in the menubar using some simple Cocoa. It does almost all that I want, except I can’t seem to get the menu to work…

EDIT: updated the script taking into account the comments and corrections from this thread!!!

Here are the steps needed:

  1. Add in your Xcode project a new file Cocoa, Objective-C Class and name it for this purpose “Menulet”. This should create two files: Menulet.h and Menulet.m

  2. In Menulet.h replace the existing code with:

#import <Cocoa/Cocoa.h>


@interface Menulet : NSObject {
}
+ (void)showMenuIcon;
@end
  1. In Menulet.m replace the existing code with:
#import "Menulet.h"


@implementation Menulet

+ (void)showMenuIcon
{
    NSStatusItem *statusItem;
		NSMenu		*theMenu;
   statusItem = [[[NSStatusBar systemStatusBar] 
      statusItemWithLength:NSVariableStatusItemLength]
      retain];
	  [statusItem setImage:[NSImage imageNamed:@"idle"]];
   [statusItem setHighlightMode:YES];
   [statusItem setTitle:[NSString 
         stringWithString:@""]]; 
   [statusItem setEnabled:YES];
   [statusItem setToolTip:@""];
   
   		theMenu = [[NSMenu alloc] initWithTitle:@""];
		[theMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"Q"];
		[statusItem setMenu:theMenu];
		[theMenu release];
}
@end
  1. Add a small image (I used size 17 by 17 and named it idle.tif) to your project (easiest is to drag it into IB)

  2. In your AppleScript you can now activate the menu bar icon by using:

call method "showMenuIcon" of class "Menulet"

Build and run…

Being a complete idiot with Cocoa I may have ignored some of its rules, so if anyone can correct this I would be grateful.

This is great work! :smiley:
But i cant help you with your problem, could you give us more information? the menubar works fine for me!

The menu bar should work fine as in the script. It’'s just that I want to add selection items linked to a script.

Yes, i see your problem :frowning:
Do you know of a way that a script could change part of the menubar coding? like for example something showing the status and in the script it has a function that calls it and changes it?

Cool thing anyway :stuck_out_tongue:

Hi Guys,

Having Never use Xcode, and having no clue what so ever of what I am doing.
I wanted to see what this does.

I made an applescript project. Made the new file.Changed the .h and .m file, But where do I put this icon, and how do I tell the app where to look for it.?

Cheers

you just need to drag any small image named idle to the “Resources” folder in your Xcode project window
no problem :expressionless:

Cheers Captainhams, I did that at a guess, as that’s where I see all the images in an app package, But the icon does not show in the menu?

Hi Mark,

Try the following:

When in Xcode double click “MainMenu.nib (English)”, this should open the program Interface Builder with your interface (which is not really used for the above purpose). In the newly opened window “MainMenu.nib (English)” you should see several tabs on top (Instances, Classes, Images, etc.). Click on the ‘Images’ tab. If you see your image file you should be ok, if not drag it into this window. I used a TIFF file, I don’t know whether it works with other file formats.

Hope this works for you,

S.

I moved NSStatusItem *statusItem; to menulet.m, because I received warnings while building.

Side note: I believe it’s proper to capitalize class names (e.g. Menulet instead of menulet).

Edit: This does work for me. Thanks for sharing, Stadsman. :cool:

After having received so much help from this forum, I’m happy to give a little back… :slight_smile:

I did not get this working,
So I tried this Menulet introduction.
Which I think is the same type of thing this thread is about, (noob talking)

Please let me know if I should start this as a new thread.

I got most of it working, but I am stuck with the drop down menu from the icon.

I can not tell if my Ipmenulet is connected to the NSMenu1 which I suspect is the problem.
It say’s

I build and Go - no errors.

But the menu does not drop down from the icon??

Also I changed the Ip url to “http://www.whatismyip.org” as the one provided did not work that well.
I could not build withou errors with (dealloc:) in, so I took it out.

Thanks

Hi Mark,

Your link is one of the sources I based my script on. Being a total cocoa noob I managed to get various scripts together to get what I wanted :stuck_out_tongue:

You have to make sure you click on ‘connect’ in the NSMenuInspector window (bottom right button).

Thats spooky :smiley:

When I drag from the Ipmenulet is connected to the NSMenu1 I do not seem to get anything show up in the inspector to select and connect to???

what is it supposed to say?

Thanks

Hi Mark,

Hopefully this screenshot explains it clearly…

Thanks Stadsman.

I do not get that.

I must have type something wrong some where, Most likely my omission of (dealloc :slight_smile:

I did add a Outlet (myOutlet) manually and change the name to theMenu, I then set the id to NSMenu
Did the drag thing, selected connect.

But still no menu.

Is it possible for you to post the .m and .h files for this so I can compare.

Thanks

Hi Mark,

Here they are, I also had to comment out (dealloc:) to get rid of the warning but it seems not to make a difference.

IPMenulet.h:

#import <Cocoa/Cocoa.h>


@interface IPMenulet : NSObject {
    NSStatusItem *statusItem;
	IBOutlet NSMenu *theMenu;
	NSMenuItem *ipMenuItem;
	NSImage *menuIcon;
}

-(IBAction)updateIPAddress:(id)sender;
@end

IPMenulet.m:

#import "IPMenulet.h"


@implementation IPMenulet
-(void)dealloc
{
    [statusItem release];
      [super dealloc];
}
- (void)awakeFromNib
{
   statusItem = [[[NSStatusBar systemStatusBar] 
      statusItemWithLength:NSVariableStatusItemLength]
      retain];
   [statusItem setHighlightMode:YES];
   [statusItem setEnabled:YES];
   [statusItem setToolTip:@"IPMenulet"];

//   [statusItem setAction:@selector(updateIPAddress:)];
//   [statusItem setTarget:self];
   [statusItem setMenu:theMenu];
   ipMenuItem = [[NSMenuItem alloc] initWithTitle:@"0.0.0.0" 
      action:@selector(updateIPAddress:) keyEquivalent:@""];
	  [ipMenuItem setTarget:self];
	[theMenu insertItem:ipMenuItem atIndex:1];
	NSBundle *bundle = [NSBundle bundleForClass:[self class]];
	NSString *path = [bundle pathForResource:@"IPMenuIcon" ofType:@"tif"];
	menuIcon= [[NSImage alloc] initWithContentsOfFile:path];

	[statusItem setTitle:[NSString stringWithString:@""]]; 
  
	[statusItem setImage];

//(dealloc:)
	[menuIcon release];
}
-(IBAction)updateIPAddress:(id)sender
{
   NSString *ipAddr = [NSString stringWithContentsOfURL:
         [NSURL URLWithString:
         @"http://www.whatismyip.org"]];
   if(ipAddr != NULL)
       [ipMenuItem setTitle:
            [NSString stringWithString:ipAddr]]; 
}
@end

Thank You.
I had three issues.

First I put

#import <Cocoa/Cocoa.h>

@interface IPMenulet : NSObject {
    NSStatusItem *statusItem;
}
-(IBAction)updateIPAddress:(id)sender;
IBOutlet NSMenu *theMenu;
NSMenuItem *ipMenuItem;
NSImage *menuIcon;
@end

As you can see the icon menu is outside the function (that may sound like I know what I am talking about, don’t be fooled. :), when I put it inside I got the correct info in the inspector.

I then found I had

[statusItem setMenu:theMenu];
ipMenuItem = [[NSMenuItem alloc] initWithTitle:@"0.0.0.0"
action:@selector(updateIPAddress:) keyEquivalent:@""];
[ipMenuItem setTarget:self];
[theMenu insertItem:ipMenuItem atIndex:1];

Above

statusItem = [[[NSStatusBar systemStatusBar] 
statusItemWithLength:NSVariableStatusItemLength]
retain];
[statusItem setHighlightMode:YES];
[statusItem setEnabled:YES];
[statusItem setToolTip:@"IPMenulet"];

// [statusItem setAction:@selector(updateIPAddress:)];
// [statusItem setTarget:self];

Once I change these the menu came up but was greyed out.

Found a missing “d” in

action:@selector(updateIPAddress:) keyEquivalent:@""];

which fixed that :smiley:

It is annoying that it compiles with no errors when there are, but I guess thats the nature of the beast.
I also notice that the intro url doe not really help in the structure of how the script should be laid out.

Thanks you for your help.

mark

Glad I could be of help, Mark.

Now another question for the Cocoa savvy:

Can I replace the ‘NULL’ statement in the following line with an action to terminate the app?

[theMenu addItemWithTitle:@"This application is active!" action:NULL keyEquivalent:@""];

I tried various variations, such as ‘NSApplication terminate’, ‘NSApp terminate’, ‘NSTerminateNow’, etc, but all to no avail… :frowning:

Ha, a new Google search did the trick:

[theMenu addItemWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"];

Hi Stadsman,
Do you know any good links to show me how I attach an applescript script to the menu.
Also my applescript opens up in Script Editor? I can not find a pref to keep it in xcode??

thanks again

mark