Menu bar icon

I’m using NSStatusBar and NSMenu in a Applescript Editor app (not Xcode) to give my app an interface on the Menu Bar. I’m doing it in Applescript Editor because I’m use the on idle handler and, correct me if I’m wrong, but you can’t use on idle in a Cocoa-Applescript app. Besides it seems a much simpler to do it in Applescript Editor.

I’d like my app to appear as an icon in the Menu Bar (currently I’ve only been able to figure out how to display text). I adapted my script from http://stackoverflow.com/questions/29168474/creating-a-simple-menubar-app-using-applescript and to be honest I don’t entirely understand what it’s doing. Here’s how I adapted it:

use framework "Foundation"
use framework "AppKit"
use scripting additions
load framework

property StatusItem : missing value
property selectedMenu : ""
property theDisplay : ""
property defaults : class "NSUserDefaults"
property internalMenuItem : class "NSMenuItem"
property externalMenuItem : class "NSMenuItem"
property newMenu : class "NSMenu"

my makeStatusBar()
my makeMenus()

on makeStatusBar()
	set bar to current application's NSStatusBar's systemStatusBar
	
	set StatusItem to bar's statusItemWithLength:-1.0
	
	-- set up the initial NSStatusBars title
	StatusItem's setTitle:"Menu Bar App"
	-- set up the initial NSMenu of the statusbar
	set newMenu to current application's NSMenu's alloc()'s initWithTitle:"Custom"
	
	newMenu's setDelegate:me (*
    Requied delegation for when the Status bar Menu is clicked  the menu will use the delegates method (menuNeedsUpdate:(menu)) to run dynamically update.


    *)
	
	StatusItem's setMenu:newMenu
	
end makeStatusBar


on makeMenus()
	
	newMenu's removeAllItems() -- remove existing menu items
	set someListInstances to {"Do something", "Do something else", "Quit"}
	
	repeat with i from 1 to number of items in someListInstances
		set this_item to item i of someListInstances
		set thisMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:this_item action:("someAction" & (i as text) & ":") keyEquivalent:"")
		
		(newMenu's addItem:thisMenuItem)
		
		(thisMenuItem's setTarget:me) -- required for enabling the menu item
	end repeat
	
end makeMenus

on someAction1:sender
	--do something
end someAction1:

on someAction2:sender
	--do something else
end someAction2:

on someAction3:sender
	quit
end someAction3:

Currently the only UI element on the Menu Bar is created using

Is it possible to substitute this for an icon of my choosing? Can this be done using Applescript Editor?

You’re right, there is no idle handler in Cocoa, but there are much more versatile ways to implement a similar function.

NSStatusItem has an image property, the type is NSImage

StatusItem's setImage:(current application's NSImage's imageNamed:"Image")

I’m sorry, I have no experience with NSImage. How would I define “Image” in

StatusItem's setImage:(current application's NSImage's imageNamed:"Image")

I think I’m way off track, but I tried loading an image from file beforehand like this:

set image to current application's NSImage's initWithContentsOfFile:"/users/tneison/desktop/image-icon.png"

Is this anywhere close?

The method NSImage(imageNamed:) creates an NSImage instance from an image in the application bundle.
But you can use also the other method initWithContentsOfFile:, but the proper syntax is

set image to current application's NSImage's alloc()'s initWithContentsOfFile:"/Users/tneison/Desktop/image-icon.png"

Wow! That’s remarkably simple. Thanks!

Hi, StefanK and tneison, I’m aware that your posts are a little “ancient”, but would you mind posting where exactly your recommended solution is to replace (or add to) tneison’s original code?
Or someone else who happens to read this and knows how-to?

(Maybe quote incl. the preceding and following lines from his 1st post?)

Btw: on MacOS 10.13.6 High Sierra I had to skip “load framework”…

I got it to use the image with

StatusItem’s setImage:newImage —newImage is path to file

but I do not know how to set it as a template image or point to resource folder. Maybe Shane or StefanK will chime in?

if the image is a bitmap image (only black and white) and the name ends with Template then the image is treated as template image automatically.

The API

 current application's NSImage's imageNamed:"IconTemplate"

looks for an image “IconTemplate” with any image extension in the application bundle