Search code examples
objective-cmacosapplescriptmenubarapplescript-objc

Creating a simple menubar app using Applescript


I am trying to create a menubar app in OS X Yosemite that simply consists of a dropdown menu with submenus. This menu and its submenus would be populated by an applescript script.

I have found tutorials on something similar before, but they all seem to be fairly outdated and don't properly work in Xcode 6.2, such as this one:

MenuApp_ASOC

I'm fairly experienced in Applescript, but haven't had much time to code in Objective C.

Where would be a good place to find a template of sorts for what I want to create?


Solution

  • This is a quick example of creating a menu system on the fly. Which is what I think you are after.

    In this example each time you click the Status bar menu the menu items will be different.

    (Yosemite required)

    Paste this code in a new Script Editor Applescript document.

    Save it as a Stay open Application using the Save as… menu option.

    Then run the app as a normal application.

        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 : "Jackson Aiden Liam Lucas Noah Mason Ethan Caden Jacob Logan Jayden Elijah Jack Luke Michael Benjamin Alexander "
    -- example list for the menu items that can be used. Ideally you will have your list created dynamically 
    
    
    -- 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 someListInstances to {}
        set counter to count of word of theList
        repeat until (count of someListInstances) is (random number from 3 to counter)
    
            set rnd to random number from 1 to counter
            set thisItem to word rnd of theList
            if thisItem is not in someListInstances then
                copy thisItem to end of someListInstances
            end if
        end repeat
        ----  <
    
        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:" keyEquivalent:"")
    
            (newMenu's addItem:thisMenuItem)
    
            (thisMenuItem's setTarget:me) -- required for enabling the menu item
            if i is equal to 3 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()