I have a question for the script below. I was testing out the “call help button” operation for the alert. When I wondered why I couldn’t just put NSAlert’s “runModal” in for the selector in “performSelectorOnMainThread …” at the end of the script. I tried both “runModal” and “NSAlert’s runModal” and neither worked. It worked when I gave a handler name as the parameter. You’ve alway done the “performSelectorOnMain …” then “runModal” after that. Are these 2 methods the equivalent? Why couldn’t I use “runModal” for the selector parameter? It seems odd it worked using an AppleScript handler but it didn’t work using an Objective C method name.
Just out of curiosity is it safe to use the script object “DisplaySpecialHelp” to implement the “help” function test. The documentation talked about an object that had a routine which could handle the alertShowHelp function and I thought of a script object. But now that I think about it the seems like a weird. But it has worked with what little testing I’ve done with it.
Bill
use AppleScript version "2.3.1"
use scripting additions
use framework "AppKit"
script DisplaySpecialHelp
on alertShowHelp:alert
display dialog "This is the special help." buttons {"OK"} default button "OK"
return true
end alertShowHelp:
end script
on DisplayAppModalDialog:theAlert
theAlert's runModal()
end DisplayAppModalDialog:
set theAlert to current application's NSAlert's alloc()'s init()
set showsHelp of theAlert to true
set delegate of theAlert to DisplaySpecialHelp
tell theAlert
its setAlertStyle:1
its setMessageText:"This is a test."
its (|window|()'s setAutorecalculatesKeyViewLoop:true)
end tell
my performSelectorOnMainThread:"DisplayAppModalDialog:" withObject:theAlert waitUntilDone:true
It has to be put in a handler so a property can be set to the result of runModal, because that’s the only way you can find out what button was pressed. It should work, as in show the alert, if you use it as the selector directly, but it won’t be of any use.
If the script object works, it works. You could also just use me as the delegate, and put the handler in the main script.
Something like this?
[edit:]
I just want to understand Bill’s question.
I mean, is the question “why a script like the one below does not return the clicked button of the main alert?”
[/edit]
-- show the main alert
set mainAlert to current application's NSAlert's alloc's init()
tell mainAlert
its setDelegate:me
its setShowsHelp:true
its setMessageText:"Main alert message."
its setInformativeText:"Main alert informative text."
its setAlertStyle:0
its addButtonWithTitle:"OK"
my performSelectorOnMainThread:(its runModal()) withObject:mainAlert waitUntilDone:true
end tell
-- show the help alert
on alertShowHelp:mainAlert
set helpAlert to current application's NSAlert's alloc's init()
tell helpAlert
its setMessageText:"Help alert message."
its setInformativeText:"Help alert informative text."
my performSelectorOnMainThread:(its runModal()) withObject:helpAlert waitUntilDone:true
end tell
return true
end alertShowHelp:
If I understand well Shane’s suggestion, the script should be:
use AppleScript version "2.4"
use scripting additions
use framework "AppKit"
property returnCode : missing value
-- show the main alert
set mainAlert to current application's NSAlert's alloc's init()
tell mainAlert
its setDelegate:me
its setShowsHelp:true
its setMessageText:"Main alert message."
its setInformativeText:"Main alert informative text."
its setAlertStyle:0
its addButtonWithTitle:"OK"
its addButtonWithTitle:"Cancel"
end tell
my performSelectorOnMainThread:"showTheAlert:" withObject:mainAlert waitUntilDone:true
returnCode
-- show the help alert
on alertShowHelp:mainAlert
set helpAlert to current application's NSAlert's alloc's init()
tell helpAlert
its setMessageText:"Help alert message."
its setInformativeText:"Help alert informative text."
my performSelectorOnMainThread:"showTheAlert:" withObject:helpAlert waitUntilDone:true
end tell
return true
end alertShowHelp:
-- check we are running in foreground
on showTheAlert:theAlert
if not (current application's NSThread's isMainThread()) as boolean then error "This handler must be called on the main thread." from current application
set my returnCode to theAlert's runModal()
end showTheAlert:
Is the performSelectorOnMainThread method absolutely necessary for the help alert or can we safely use runModal here?
(Also I’m noticing that the “Open in Script Debugger” link in Bill’s script doesn’t work. I’ve quit and relaunched SD and Safari, and it seems to have no effect. The link seems active, the cursor changes to the pointer and the link changes color when I hover, but it seems to have no effect. Other “Open in Script Debugger” links in the forum are still working.)
Anything that results in screen drawing should generally be done on the main thread. If you’re not sure, have Console open as you run the relevant code – you’ll see warnings (or a crash) if you’re doing the wrong thing.
At the top of the script you posted in this thread the forum added a link that reads “Open in Script Debugger” Click on it and your script opens in a new, uncompiled SD window/tab.
I’m not sure by what magic the system recognizes it’s a script, but I think putting four spaces at the start works. (That’s probably documented somewhere)