There are times when display dialog and display alert are not quite enough. If you're running Mavericks or Yosemite, AppleScriptObjC gives you more options, in particular by giving you access to extra possibilities with alerts.
Two simple possibilities are the ability to have more than three buttons -- something not really needed often, but sometimes justified -- and the ability to include a Do not show this message again checkbox, known as a suppression button. A more complex option is to include an accessory view -- an area above the buttons where you can add extra controls.
Alerts also lend themselves more to being coded as handlers, making them ideal to store in script libraries. By storing them in script libraries, you also make them accessible from Mavericks. (In fact, in Mavericks they have to be in libraries.)
Before getting down to code, it's probably worth discussing the process. First, you create a new NSAlert, using either the new() or alloc() and init() methods. It's roughly equivalent to "make new..." in traditional AppleScript. You can then set various properties -- alertStyle, messageText, informativeText and showsSuppressionButton. Buttons are added one at a time, from right to left, using addButtonWithTitle:. The right-most button is always the default button, and a button called "Cancel" (or localized equivalent) responds to the escape key or command-..
After that, you show the dialog by calling runModal(), which returns a number that relates to the button that was pressed.
The handler below takes an integer for the style, and a list of button titles from left-to-right, to match the standard AppleScript order; the code then reverses the order before adding them. It uses the result of runModal() to work out the button title, and it is ignoring the suppression button for the moment.
Before you run the code, a warning: ASObjC code that involves drawing stuff on screen, like this, has to be run in the foreground on what is known as the main thread. If it is run on a background thread, the likely result is that the app will crash. Scripts are nearly always run on the main thread -- the one exception being in script editors, where they are usually run on background threads. So when you are trying out this code, you need to make sure you run it in the foreground.
In Script Editor, you run a script in the foreground by holding the control key when running it, or pressing control-command-R. You can see the Run command change names in the Script menu when you hold down the control key. In ASObjC Explorer you check the 'Run in foreground' checkbox at the bottom of the script window.
Because it is easy to forget when you are testing, especially in Script Editor, I've added some extra code that checks if it is running in the foreground, and if not shows a dialog and stops, rather than letting the app crash. This simply asks the NSThread class if the current code is on the main thread.
use AppleScript version "2.4" use scripting additions use framework "Foundation" use framework "AppKit" -- required for NSAlert
-- check we are running in foreground 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
-- for styleNum, 0 = warning, 1 = informational, 2 = critical on displayAlert:mainText message:theExplanaton asStyle:styleNum buttons:buttonsList set buttonsList to reverse of buttonsList -- because they get added in reverse order cf AS -- create an alert set theAlert to current application's NSAlert's alloc()'s init() -- set up the alert tell theAlert its setAlertStyle:styleNum its setMessageText:mainText its setInformativeText:theExplanaton repeat with anEntry in buttonsList (its addButtonWithTitle:anEntry) end repeat end tell -- show the alert set returnCode to theAlert's runModal() -- get values after alert is closed set buttonNumber to returnCode mod 1000 + 1 -- where 1 = right-most button set buttonName to item buttonNumber of buttonsList return buttonName end displayAlert:message:asStyle:buttons:
set buttonName to (my displayAlert:"Stay alert" message:"This is the 9 o'clock news" asStyle:2 buttons:{"Cancel", "Maybe", "Possibly", "Perhaps", "Probably", "OK"})
|