Hi, I use a NSSavePanel
in a script that I’d like to use in Script Debugger’s scripts menu. While writing everything worked as expected, however the panel doesn’t get focus when it’s run from the menu. To see whether I’m missing something I made a test script and ran it from DEVONthink’s and Script Debugger’s menu. In DEVONthink the panel gets focus, in Script Debugger it doesn’t. Any way to get focus on the panel?
Are you preceding it by a call to activate?
tell application id "com.latenightsw.ScriptDebugger8" to activate
It works for me like that.
Already tried that, no luck.
Here’s (a part of) the script. The complete script shows the panel with the suggested filename taken from the first line (e.g. -- Task: Try - Save Panel
) and the default directory from the frontmost Path Finder window. It’s part of an attempt to get more structure into the repos I use for learning ASObjC.
What I don’t get: the panel gets focus if the executed script is opened (but not the frontmost window) and run via the menu, but if it’s not opened I can’t get it focused (tried activate
almost everywhere but removed it afterwards).
Still using macOS 10.14.6 btw
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use framework "Carbon"
use scripting additions
property theDirectoryPath_Default : POSIX path of (path to desktop)
property theAllowedFileTypes : {"applescript", "scpt", "scptd", "app"}
property theSavePanel_Message : ""
property theSavePanel_NameFieldLabel : ""
property theSavePanel_Prompt : ""
property theSavePanel : missing value
property theSavePanel_ReturnCode : missing value
tell application id "com.latenightsw.ScriptDebugger8"
try
set theWindow to script window 1
set theDoc to current document of theWindow
if file spec of theDoc ≠ missing value then error "Skript ist bereits gespeichert"
tell theDoc
set theSource to source text
set theLines to paragraphs of theSource
set theLine to item 1 of theLines
set theLineWithoutKey to (characters 10 thru -1 in theLine) as string
if theLineWithoutKey contains " - " then
set thePrefixDelimiterOffset to offset of " - " in theLineWithoutKey
set thePrefix to characters 1 thru (thePrefixDelimiterOffset - 1) in theLineWithoutKey as string
set theName to (characters (thePrefixDelimiterOffset + 3) thru -1 in theLineWithoutKey) as string
else
set thePrefix to missing value
set theName to theLineWithoutKey
end if
end tell
on error error_message number error_number
if the error_number is not -128 then display alert "Script Debugger" message error_message as warning
return
end try
end tell
-- (removed stuff that gets path of Path Finder window)
set theDirectoryPath to theDirectoryPath_Default -- testing
set theName to "A name" -- testing
tell application id "com.latenightsw.ScriptDebugger8"
try
activate
set {thePath, theExtension} to my saveFile(theDirectoryPath, theName, theAllowedFileTypes)
tell theDoc
if theExtension = "applescript" then
save as text script in POSIX file thePath
else if theExtension = "scpt" then
save as compiled script in POSIX file thePath
else if theExtension = "scptd" then
save as bundled compiled script in POSIX file thePath
else if theExtension = "app" then
save as script application in POSIX file thePath
end if
end tell
on error error_message number error_number
if the error_number is not -128 then display alert "Script Debugger" message error_message as warning
return
end try
end tell
on saveFile(theDirectoryPath_Default, theSuggestedFileName, theAllowedFileTypes)
try
if current application's AEInteractWithUser(-1, missing value, missing value) ≠ 0 then error number -1713 from current application
set theDefaultPathURL to current application's |NSURL|'s fileURLWithPath:theDirectoryPath_Default
set theSavePanelRecord to {allowedFileTypes:theAllowedFileTypes, allowsOtherFileTypes:false, canCreateDirectories:true, directoryURL:theDefaultPathURL, extensionHidden:false, message:theSavePanel_Message, nameFieldLabel:theSavePanel_NameFieldLabel, nameFieldStringValue:theSuggestedFileName, prompt:theSavePanel_Prompt, showsTagField:false}
its performSelectorOnMainThread:"displaySavePanel:" withObject:theSavePanelRecord waitUntilDone:true
if theSavePanel_ReturnCode is (current application's NSFileHandlingPanelCancelButton) then error number -128
set thePath to (theSavePanel's |URL|()'s |path|())
set theExtension to thePath's pathExtension()
return {thePath as string, theExtension as string}
on error error_message number error_number
activate
if the error_number is not -128 then display alert "Error: Handler \"saveFile\"" message error_message as warning
error number -128
end try
end saveFile
on displaySavePanel:theSavePanelRecord
try
if (current application's NSThread's isMainThread()) = false then error "Handler kann nur auf Main Thread genutzt werden." from current application
set theSavePanel to current application's NSSavePanel's savePanel()
tell theSavePanel
its setAllowedFileTypes:(allowedFileTypes of theSavePanelRecord)
its setAllowsOtherFileTypes:(allowsOtherFileTypes of theSavePanelRecord)
its setCanCreateDirectories:(canCreateDirectories of theSavePanelRecord)
its setDirectoryURL:(directoryURL of theSavePanelRecord)
its setExtensionHidden:(extensionHidden of theSavePanelRecord)
its setMessage:(message of theSavePanelRecord)
its setNameFieldLabel:(nameFieldLabel of theSavePanelRecord)
its setNameFieldStringValue:(nameFieldStringValue of theSavePanelRecord)
its setPrompt:(prompt of theSavePanelRecord)
its setShowsTagField:(showsTagField of theSavePanelRecord)
end tell
set my theSavePanel_ReturnCode to theSavePanel's runModal()
on error error_message number error_number
activate
if the error_number is not -128 then display alert "Error: Handler \"displaySavePanel\"" message error_message as warning
error number -128
end try
end displaySavePanel:
It’s a curious behavior of NSScriptUserTask
. When the script is open, it uses SD as host, whereas otherwise it uses osascript
. You can see it fairly clearly in Activity Monitor. (At least, I can in 10.15.)
I can’t see any obvious solution other than to save it as an applet, with the resulting delay in launching.
Saving as applet is ok. Thanks a lot for looking into this!