Wednesday, December 8, 2021

#1 2021-07-06 04:41:42 am

Fredrik71
Member
Registered: 2019-10-23
Posts: 917

Example of NSStatusBar, NSMenu and NSMenuItem

Simple example of NSStatusBar, NSMenu and NSMenuItem to perform action...
If you make a applet you need to add things in the info.plist
<key>LSUIElement</key>
<true/>

It makes the icon of dock to be hidden, and in the script we use if statement to tell me to quit

Ps. If you use Script Debugger you could change in the script.

The script could be run directly from Script Editor.

Applescript:

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

(** add to info.plist in the applet
* <key>LSUIElement</key>
* <true/>
*)


property itemStatus : missing value

on run
   set arguments to {"Action 1", "|", "Action 2", "|", "Action 3", "|", "Action 4", "|", "Action 5", "|", "Action 6", "|", "Action 7", "|", "Quit"}
   if my NSThread's isMainThread() as boolean then
       my performMenuStatusbar:arguments
   else
       my performSelectorOnMainThread:"performMenuStatusbar:" withObject:arguments waitUntilDone:true
   end if
end run

on performMenuStatusbar:arguments
   set menuList to arguments
   set theMenu to createMenu(menuList)
   set itemStatus to (current application's NSStatusBar's systemStatusBar())'s statusItemWithLength:(current application's NSVariableStatusItemLength)
   itemStatus's setTitle:"Action Menu"
   itemStatus's setHighlightMode:true
   itemStatus's setMenu:theMenu
end performMenuStatusbar:

on createMenu(menuList)
   set theMenu to current application's NSMenu's alloc()'s init()
   set theCount to 1
   repeat with i in menuList
       if (contents of i) as string is not "|" then
           set menuItem to (current application's NSMenuItem's alloc()'s initWithTitle:(contents of i) action:"actionHandler:" keyEquivalent:"")
       else
           set menuItem to current application's NSMenuItem's separatorItem()
       end if
       (menuItem's setTarget:me)
       (menuItem's setTag:theCount)
       (theMenu's addItem:menuItem)
       if (contents of i) as string is not "|" then
           set theCount to theCount + 1
       end if
   end repeat
   return theMenu
end createMenu

on actionHandler:sender
   set menuTitle to title of sender as string
   
   if menuTitle is "Quit" then
       current application's NSStatusBar's systemStatusBar()'s removeStatusItem:itemStatus
       if (name of current application) is not "Script Editor" then
           tell me to quit
       end if
   else if menuTitle is "Action 1" then
       display dialog "This is action 1..."
   else if menuTitle is "Action 2" then
       display dialog "This is action 2..."
   else if menuTitle is "Action 3" then
       display dialog "This is action 3..."
   else if menuTitle is "Action 4" then
       display dialog "This is action 4..."
   else if menuTitle is "Action 5" then
       display dialog "This is action 5..."
   else if menuTitle is "Action 6" then
       display dialog "This is action 6..."
   else if menuTitle is "Action 7" then
       display dialog "This is action 7..."
   end if
end actionHandler:


if you are the expert, who will you call if its not your imagination.

Offline

 

#2 2021-07-06 02:30:24 pm

Fredrik71
Member
Registered: 2019-10-23
Posts: 917

Re: Example of NSStatusBar, NSMenu and NSMenuItem

I update other script here on macscripter:
https://www.macscripter.net/viewtopic.p … 09#p196609

This one include subMenu and 4 actions and some useful logging.

Could be run directly in Script Editor or as applet...

Applescript:

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

(** add to info.plist in the applet
* <key>LSUIElement</key>
* <true/>
*)


property theStatusItem : missing value

on run
   set theStatusBar to showStatusBar given arguments:{"ActionGroup 1", {"Action 1", "Action 2"}, "ActionGroup 2", {"Action 3", "Action 4"}, "", "Quit"}
end run

on showStatusBar given arguments:arguments
   if my NSThread's isMainThread() as boolean then
       my performMenuStatusbar:arguments
   else
       my performSelectorOnMainThread:"performMenuStatusbar:" withObject:arguments waitUntilDone:true
   end if
end showStatusBar

on performMenuStatusbar:arguments
   set menuList to arguments as list
   set theMenu to createMenu(menuList)
   set theStatusBar to createStatusBar("Action", theMenu)
end performMenuStatusbar:

on createStatusBar(theTitle, menuList)
   -- Returns the system-wide status bar located in the menu bar.
   set theStatusBar to current application's NSStatusBar's systemStatusBar()
   -- A status item length that dynamically adjusts to the width of its contents.
   set theStatusItem to theStatusBar's statusItemWithLength:(current application's NSVariableStatusItemLength)
   theStatusItem's setTitle:theTitle
   theStatusItem's setImage:(current application's NSImage's imageNamed:(current application's NSImageNameActionTemplate))
   theStatusItem's setHighlightMode:true
   log theStatusItem's |description|() as text
   theStatusItem's setMenu:menuList
   log theStatusItem's button()'s |description|() as text
   log theStatusItem's |menu|()'s |description|() as text
   return theStatusItem
end createStatusBar

on createMenu(menuList)
   set theMenu to current application's NSMenu's alloc()'s init()
   set {theCount, prevMenuItem} to {10, ""}
   
   repeat with i in menuList
       if (contents of i) is equal to "" then
           set theMenuItem to (current application's NSMenuItem's separatorItem())
           (theMenu's addItem:theMenuItem)
           
       else if ((class of (contents of i)) as string) = "list" then
           --Generate Submenu
           set subMenu to current application's NSMenu's alloc()'s init()
           (theMenuItem's setSubmenu:subMenu)
           set subCounter to 1
           
           repeat with j in (contents of i)
               set subMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:(contents of j) action:"actionHandler:" keyEquivalent:"")
               (subMenuItem's setTarget:me)
               (subMenuItem's setTag:(theCount + subCounter))
               (subMenu's addItem:subMenuItem)
               set subCounter to subCounter + 1
           end repeat
       else
           set theMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:(contents of i) action:"actionHandler:" keyEquivalent:"")
           (theMenuItem's setTag:theCount)
           (theMenuItem's setTarget:me)
           (theMenu's addItem:theMenuItem)
           set theCount to theCount + 10
           copy theMenuItem to prevMenuItem
       end if
   end repeat
   return theMenu
end createMenu

on actionHandler:sender
   set menuTitle to title of sender as string
   
   if menuTitle is "Quit" then
       current application's NSStatusBar's systemStatusBar()'s removeStatusItem:theStatusItem
       if (name of current application) is not "Script Editor" then
           tell me to quit
       end if
   else if menuTitle is "Action 1" then
       display dialog "This is action 1..."
   else if menuTitle is "Action 2" then
       display dialog "This is action 2..."
   else if menuTitle is "Action 3" then
       display dialog "This is action 3..."
   else if menuTitle is "Action 4" then
       display dialog "This is action 4..."
   end if
end actionHandler:

Last edited by Fredrik71 (2021-07-06 02:34:30 pm)


if you are the expert, who will you call if its not your imagination.

Offline

 

#3 2021-07-06 03:10:06 pm

Fredrik71
Member
Registered: 2019-10-23
Posts: 917

Re: Example of NSStatusBar, NSMenu and NSMenuItem

If we like to run script with paramers... we could do something like this...

Make AppleScript with name: scriptToRun.scpt and save it to desktop.

Applescript:

on run {input, parameters}
   display dialog "My running script from menu status bar with: " & parameters
end run

Now open the script below and run...

EDIT: 210707 Have clean-up the original code and add a separator character for menu and submenu.

Applescript:

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

(** add to info.plist in the applet
* <key>LSUIElement</key>
* <true/>
**
* on run {input, parameters}
*    display dialog "My running script from menu status bar with: " & parameters
* end run
*)


property theStatusItem : missing value

on run
   set theStatusBar to showStatusBar given arguments:{"Action Group 1", {"Action 1", "|", "Action 2", "Action 3", "Action 4"}, "Action Group 2", {"Action 5", "|", "Action 6"}, "|", "Quit"}
end run

on showStatusBar given arguments:arguments
   if my NSThread's isMainThread() as boolean then
       my performMenuStatusbar:arguments
   else
       my performSelectorOnMainThread:"performMenuStatusbar:" withObject:arguments waitUntilDone:true
   end if
end showStatusBar

on performMenuStatusbar:arguments
   set menuList to arguments as list
   set theMenu to createMenu(menuList, "|")
   set theStatusBar to createStatusBar("Action", theMenu)
end performMenuStatusbar:

on createStatusBar(theTitle, menuList)
   -- Returns the system-wide status bar located in the menu bar.
   set theStatusBar to current application's NSStatusBar's systemStatusBar()
   -- A status item length that dynamically adjusts to the width of its contents.
   set theStatusItem to theStatusBar's statusItemWithLength:(current application's NSVariableStatusItemLength)
   theStatusItem's setTitle:theTitle
   theStatusItem's setImage:(current application's NSImage's imageNamed:(current application's NSImageNameActionTemplate))
   theStatusItem's setHighlightMode:true
   log theStatusItem's |description|() as text
   theStatusItem's setMenu:menuList
   log theStatusItem's button()'s |description|() as text
   log theStatusItem's |menu|()'s |description|() as text
   return theStatusItem
end createStatusBar

on createMenu(menuList, seperator)
   set theMenu to current application's NSMenu's alloc()'s init()
   set theCount to 1
   
   repeat with i in menuList
       if (contents of i) as string is seperator then
           set theMenuItem to (current application's NSMenuItem's separatorItem())
           (theMenu's addItem:theMenuItem)
           
       else if ((class of (contents of i)) as string) = "list" then
           --Generate Submenu
           set subMenu to current application's NSMenu's alloc()'s init()
           (theMenuItem's setSubmenu:subMenu)
           
           repeat with j in (contents of i)
               if (contents of j) as string is seperator then
                   set theMenuItem to (current application's NSMenuItem's separatorItem())
                   (subMenu's addItem:theMenuItem)
               else
                   set subMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:(contents of j) action:"actionHandler:" keyEquivalent:"")
                   (subMenuItem's setTarget:me)
                   (subMenuItem's setTag:theCount)
                   (subMenu's addItem:subMenuItem)
               end if
           end repeat
       else
           set theMenuItem to (current application's NSMenuItem's alloc()'s initWithTitle:(contents of i) action:"actionHandler:" keyEquivalent:"")
           (theMenuItem's setTag:theCount)
           (theMenuItem's setTarget:me)
           (theMenu's addItem:theMenuItem)
           set theCount to theCount + 1
       end if
   end repeat
   return theMenu
end createMenu

on actionHandler:sender
   set menuTitle to title of sender as string
   
   if menuTitle is "Quit" then
       current application's NSStatusBar's systemStatusBar()'s removeStatusItem:theStatusItem
       if (name of current application) is not "Script Editor" then
           tell me to quit
       end if
   else if menuTitle is "Action 1" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 1"}
   else if menuTitle is "Action 2" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 2"}
   else if menuTitle is "Action 3" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 3"}
   else if menuTitle is "Action 4" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 4"}
   else if menuTitle is "Action 5" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 5"}
   else if menuTitle is "Action 6" then
       run script POSIX path of (path to desktop) & "scriptToRun.scpt" with parameters {"", "Action 6"}
   end if
end actionHandler:

Last edited by Fredrik71 (2021-07-07 06:15:54 am)


if you are the expert, who will you call if its not your imagination.

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)