Set bounds property for "choose from list" in AppleScript? - applescript

I'm making an applet that prompts users to choose from a list, and my list currently has 169 items. When the list is generated, the window extends from the top of the display to the bottom, a bit overwhelming for a user.
I'm wondering if anyone knows of a way to edit the bounds property of the window generated by "choose from list?"
Here's the code I'm using (not including separate code to compile the list and store it in "pkgList"):
set userChoice to (choose from list pkgList with title "Title" with prompt "Choose file:" OK button name "OK" cancel button name "Cancel" without empty selection allowed) as string
I'm very new to AppleScript, so detailed explanations and analogies are much appreciated. :)

You might use CocoaDialog instead:
set l to {"a a", "b"}
set l2 to ""
repeat with i in l
set l2 to l2 & quoted form of i & " "
end repeat
do shell script "/Applications/CocoaDialog.app/Contents/MacOS/CocoaDialog \\
standard-dropdown --title Title --text Text --items " & l2
set {button, answer} to paragraphs of result
if button is 1 then return
item {answer + 1} of l

Related

How can I use AppleScript to find disabled menu items?

I have an AppleScript script that will find all of the menu items from all of the menu bar menus. I've filtered out each separator, so I have just the commands, and now I'd like to find out how to find out which menu items are disabled. Does anybody know how I could do that?
Update:
Here's the code I have to get the names of each menu command. It's working fine, and I tried to get the menu items that were enabled in the getAppMenuItems, but it just returned all the menu items, missing values too.
set appName to "Script Editor"
set allMenus to {}
set everything to {}
set onlyEnabled to {}
tell application "System Events" to tell process appName
set allMenus to name of every menu of menu bar 1
end tell
repeat with menuName in allMenus
set the end of everything to strings of getAppMenuItems(appName, menuName, onlyEnabled)
end repeat
on getAppMenuItems(appProcess, appMenus, enabledItems)
tell application "System Events" to tell process appProcess
(*
# Get all menu items
set theItems to every menu item of menu appMenus of menu bar 1
repeat with i from 1 to number of items in theItems
set thisItem to item i of theItems
if thisItem is not enabled then
log ("Item: " & name of thisItem & " is enabled")
set the end of enabledItems to the name of thisItem
end if
end repeat
*)
return name of every menu item of menu appMenus of menu bar 1
end tell
end getAppMenuItems
# From the commented part of the 'getAppMenuItems' function above.
# When that part of the function is uncommented, I just get everything,
# missing values and all
onlyEnabled
# Edit Menu
item 4 of everything
(* Outputs: Half of these items are not enabled
{"Undo", "Redo", "Cut", "Copy", "Paste", "Paste and Match Style", "Paste Reference", "Delete", "Select All", "Complete", "Find", "Spelling and Grammar", "Substitutions", "Transformations", "Speech", "Start Dictation…", "Emoji & Symbols"} *)
In order to get the properties of a menu item, you first need to get a reference to that menu item. You would then need to go through the various menu items and build lists or records of those that meet your criteria, so that the references can be used as needed.
From the comments, general-purpose handlers to click at or get menu references by using a list of the menu hierarchy would serve your purpose, so those would be something like:
on run -- examples
#clickMenu at {"Finder", "View", 10, "Name"} -- note that there are 2 "Clean Up" items
set menuRef to getMenuReference for {"Script Editor", "File", "New"}
log result
clickMenu at menuRef -- clickMenu at {"Script Editor", "File", "New"} can also be used
end run
to getMenuReference for menuList -- Get a reference to a menu item in an application's main menu.
(*
The menu hierarchy is described in the menuList parameter.
The last menu item doesn't need to be exact, just close enough for a match.
Menu items can also be integer indexes (separators are counted).
When using an index, note that menus can contain dynamic or hidden items.
parameters: menuList [list] -
item 1 [text]: the application name
item 2 [text]: the menu bar item name
item(s) 3+ [text or integer]: the (sub)menu item(s)
returns the reference or missing value
*)
try
set itemCount to (count menuList) -- needs to be at least {application, menu, item}
if itemCount < 3 then error "menuReference handler: the menu item list contains too few items"
set {appName, menuName} to items 1 thru 2 of menuList
set {menuItem, found} to {last item of menuList, false}
tell application appName to activate
tell application "System Events" -- set up the menu path
set appName to (name of application processes whose frontmost is true) as text -- handle different process names
set menuPath to menu menuName of menu bar item menuName of menu bar 1 of application process appName
if itemCount > 3 then repeat with i from 3 to (itemCount - 1) -- add sub menu items
set menuName to item i of menuList
if class of menuName is integer then set menuName to item menuName of (get name of menu items of menuPath)
set menuPath to menu (menuName as text) of menu item (menuName as text) of menuPath
end repeat
if class of menuItem is not integer then -- the target menu item
repeat with anItem in (get name of menu items of menuPath)
if anItem begins with (menuItem as text) then -- match a partial string (also 'contains', etc)
set {menuItem, found} to {anItem, true}
exit repeat
end if
end repeat
if not found then error "menuReference handler: menu item " & quoted form of menuItem & " not found"
end if
return menu item menuItem of menuPath
end tell
on error errorMessage number errorNumber
log errorMessage
# error errorMessage number errorNumber -- uncomment to pass error up the chain
end try
return missing value
end getMenuReference
to clickMenu at menuItem -- Click a menu item in an application's main menu.
(*
The menuItem can be a reference to the menu item or a list of the menu hierarchy.
parameters: menuItem [reference or list] - see the getMenuReference handler
returns true if successful, false otherwise
*)
try
if class of menuItem is list then -- get a reference
set menuItem to getMenuReference for menuItem
if menuItem is missing value then error "clickMenu handler: the menu item was not found"
end if
tell application "System Events"
# log (get properties of menuItem)
if (enabled of menuItem) then -- filter for desired property
click menuItem
delay 0.25
return true -- success
end if
end tell
on error errorMessage number errorNumber
log errorMessage
# error errorMessage number errorNumber -- uncomment to pass error up the chain
end try
return false -- failure
end clickMenu

How can I make a menu item change its label when I press and hold the option key?

I want to be able to make a menu item a bit more powerful by having an alternate behavior when the option key is held and clicked. What I need is similar to when you press the option button in Finder, where you get the option "Copy 'seletedfile' as Pathname". How is this accomplished in AppleScript/Objective-C?
Here's my template code for creating regular menu items:
set menuItems to {"POC1", "POC2"}
repeat with i from 1 to number of items in menuItems
set this_item to item i of menuItems
if i is equal to selectedIndex then set this_item to this_item & " " & (emoji's CHECK)
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

How to Send the Output of a Dialog Box to an email adress in applescript

I would like to be able to send the output of a dialog box to my email. What would be the best way to do such a thing?
It would be something sort of like this:
repeat
display dialog "Enter some text:" buttons {"Git Goin"} default answer ""
set theNewInfo to text returned of result
if theNewInfo ≠ "" then exit repeat
end repeat
Its a really simple script for a proof of concept, but what I want is as follows: When they enter any text into the dialog box, for that text to be sent to my email, regardless of what it contains.The Subject would say "NewInfo" and the body would contain the text entered into the dialog box
You should post what code you have... too many questions still to be able to answer you reliably. What are you wanting to send to the email message? email addy? subject? body? etc.
Basically, you capture the result of the dialog and then put it into a "mailto:" URL string and then use 'open location' on the URL. This should be enough to get you started:
set dialogResult to display dialog "Enter the subject" default answer "My subject" buttons {"me#example.com", "you#example.com"} default button 1
set theAddress to button returned of dialogResult
set theSubject to text returned of dialogResult
set theBody to "This%20is%20the%20body%20text:%0AMore%20text"
-- Must encode entities, spaces as %20 and line breaks as %0A (%0D%0A), etc.
set theSubject to findReplace(" ", "%20", theSubject)
set theSubject to findReplace(return, "%0A", theSubject)
set theURL to "mailto:" & theAddress & "?subject=" & theSubject & "&body=" & theBody
open location theURL
on findReplace(f, r, s)
set otid to AppleScript's text item delimiters
set AppleScript's text item delimiters to f
set s to text items of s
set AppleScript's text item delimiters to r
set s to s as string
set AppleScript's text item delimiters to otid
return s
end findReplace

The variable result is not defined AppleScript

I am working on the same app that I mentioned in my first question. I have gotten much farther, but when I try to play "2048" the first time, AppleScript give me the error:
"The variable result is not defined"
I will skip the main bulky body of the app and get to the area with the problem:
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
else
display dialog "Invalid response" with title "Invalid response" buttons {"Go back", "Quit"} default button 1
end if
if the button returned of the result is "Go back" then
display dialog "What would you like to do?
Sleep = Go to sleep
Finder = Open Finder
Time = Display current time and date
2048 = play 2048
Quit = Quit application" default answer "" with title "Control panel"
else
return
end if
if the text returned of the result is "Sleep" then
tell application "System Events" to sleep
display dialog "Hello, welcome back!" buttons {"Thank you!"} default button 1
return
else if the text returned of the result is "Finder" then
tell application "Finder" to make new Finder window
else if the text returned of the result is "Time" then
set a to (current date) as list
set AppleScript's text item delimiters to linefeed
set a to a as text
display dialog a buttons {"OK"} default button 1
else if the text returned of the result is "Quit" then
return
else if the text returned of the result is "2048" then
tell application "Terminal"
do script "/Users/student/Documents/2048.sh"
activate
end tell
end if
Just set the result of the display dialog to a variable and use the variable. It's tricky to use "result" as you have in many if statements. One of them is bound to cause a problem because "result" will change at some point.
So do something like this right after your display dialog statement...
set {buttonReturned, textReturned} to {button returned of result, text returned of result}
Then in your if statements use buttonReturned or textReturned.

How do I mimic pressing the "down" arrow in vb6?

I made a form and created a command button control. I would like to make it so that when the user presses the command button it sends a keystroke to a listbox of my choice.
Specifically, I want the command button to send a "down" arrow keystroke to a listbox (which will have focus) so that it goes from the current item to the next item.
How do I do this?
Let's say the name of my listbox is "lstFruits". I gave it focus, then tried SendKey.
Form.lstFruits.SetFocus.
SendKeys.Send ("{DOWN}")
Got the error "Argument not optional".
There is no need to emulate a keystroke, you can control the listbox in code;
lstFruits.SetFocus
if ((lstFruits.listindex + 1) < lstFruits.listcount) then
lstFruits.listindex = lstFruits.listindex+ 1
endif
Edit
Dim strName As String
strName = "lstFruits"
Dim lst As VB.ListBox: Set lst = TheForm.Controls(strName)
lst.SetFocus
If ((lst.ListIndex + 1) < lst.ListCount) Then
lst.ListIndex = lst.ListIndex + 1
End If

Resources