menuapplescriptmenuitemapplescript-objcnsapplescript

Make Menu Item Do Something AppleScript


I'm writing a program in AppleScript that creates a menu in the menu bar on MacOS. This is my code:

use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property StatusItem : missing value
property selectedMenu : "" -- each menu action will set this to a number, this will determin which IP is shown

property theDisplay : ""
property defaults : class "NSUserDefaults"
property internalMenuItem : class "NSMenuItem"
property externalMenuItem : class "NSMenuItem"
property newMenu : class "NSMenu"

property theList : "Settings Battery Quit"
-- example list for the menu items that can be used. Ideally you will have your list created dynamically
(*MENU ITEMS
- Settings
- Battery Stats
----------
- Quit
*)


-- check we are running in foreground - YOU MUST RUN AS APPLICATION. to be thread safe and not crash
if not (current application's NSThread's isMainThread()) as boolean then
    display alert "This script must be run from the main thread." buttons {"Cancel"} as critical
    error number -128
end if

on menuNeedsUpdate:(menu)
    (* NSMenu's delegates method, when the menu is clicked this is called.

    We use it here to call the method makeMenus(). Which removes the old menuItems and builds new ones.

    This means the menu items can be changed dynamically.

    *)
    
    my makeMenus()
end menuNeedsUpdate:

on makeMenus()
    newMenu's removeAllItems() -- remove existing menu items
    -----< (* this is just to show in this example a dynamic list for the menu items
    set allMenuItems to {"Settings", "Battery Stats", "Quit"}
    ----  <
    
    repeat with i from 1 to number of items in allMenuItems
        set this_item to item i of allMenuItems
        set thisMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:this_item action:"someAction:" keyEquivalent:"")
        
        (newMenu's addItem:thisMenuItem)
        
        (thisMenuItem's setTarget:me) -- required for enabling the menu item
        if i is equal to 2 then
            (newMenu's addItem:(current application's NSMenuItem's separatorItem)) -- add a seperator
        end if
    end repeat
    
end makeMenus



--menuItems  action is requied for the menu to be enabled
on someAction:sender
    MenuItem --do some thing
end someAction:

-- create an NSStatusBar
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:"IP"
    -- 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


my makeStatusBar()

The function

on someAction:sender
    --MenuItem --do some thing
end someAction:

is what I need to change. I don't know how to run specific tasks based on which menu item is clicked. When I put code straight in the function:

on someAction:sender
    --MenuItem --do some thing
        display dialog "This runs on menu item click"
end someAction:

then the code runs whenever ANY menu item is clicked. I want it to run specific tasks for specific menu items. The menu items are:

Settings
Battery Stats
Quit

I tried this:

on someAction:sender
    --MenuItem --do some thing
    if sender is equal to "Settings"
    --Code here!
    end if
    end someAction:

However, nothing happened when I clicked "Settings" in the menu.

Any help would be appreciated!


Solution

  • You can run specific tasks for specific menu items by checking the sender title:

    on someAction:sender
        set theTitle to title of sender as string
        if theTitle is "Settings" then
            display dialog "This runs when menu item \"Settings\" clicked"
        else if theTitle is "Battery Stats" then
            display dialog "This runs when menu item \"Battery Stats\" clicked"
        else if theTitle is "Quit" then
            quit
        else
            -- do nothing
        end if
    end actionHandler: