How to positioning a "Choice from List"-window?

Is there a way to positioning a choice from List Box at a defined position on the screen (eg. top left corner)? The dialog needs to be started out of the “Photos” application. By default the dialog box appears in the middle where I don’t want it to be.

Next, how to bring up the “Photos” window out of the Dock (when it is minimised in the dock) and how to adjust its size? With the command “activate” it will just be activated but not expanded out of the dock.

How can then the Photo Window positioned for excample at 100,0 somewhere next to the Choice Box?

tell application "Photos"
	set Choice to {"one", "two", "three"}
	set ChooesenNo to choose from list Choice with prompt "Choose number"
end tell

i think by pos he’s referring to screen coordinates of where the dialog appears, not the position in the list.

I don’t know how to position the choose from list dialog. As regards the above, try the following, which worked on my Sonoma computer.

tell application "System Events" to tell process "Photos"
	set position of window 1 to {33, 53} -- set to desired value
	set size of window 1 to {888, 888} -- set to desired value
end tell

tell application "Photos"
	reopen
	activate
end tell

Try this

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

on run xargs
	if (class of xargs) = list then
		set p to item 1 of xargs
		tell application "System Events" to tell application process p
			repeat until exists (window 1 whose subrole is "AXDialog")
				delay 0.1
			end repeat
			set mywin to window 1 whose subrole is "AXDialog"
			get properties of mywin
			set position of mywin to {1700, 600}
			beep
		end tell
	else
		set cPath to quoted form of (POSIX path of (path to me))
		do shell script "osascript " & cPath & " '" & (name of current application) & "' &>/dev/null &"
		set ans to choose from list {1, 2, 3, 4}
	end if
	return ans
end run

Here is a slightly modified version that also send s the title of the Dialog, so it can be found by the title, incase there are more than one dialog windows open in whatever app is running the script.

on run xargs
	local proc, Dtitle
	if (class of xargs) = list then -- it was called from the command line
		set proc to item 1 of xargs
		set Dtitle to item 2 of xargs
		tell application "System Events" to tell application process proc
			repeat until exists (window 1 whose title is Dtitle) --(window 1 whose subrole is "AXDialog")
				delay 0.05
			end repeat
			set mywin to window 1 whose title is Dtitle
			set position of mywin to {random number from 30 to 3000, random number from 30 to 1200}
		end tell
	else
		set cPath to quoted form of (POSIX path of (path to me))
		set Dtitle to "List Chooser"
		do shell script "osascript " & cPath & " '" & (name of current application) & "' '" & Dtitle & "' &>/dev/null &"
		set ans to choose from list {1, 2, 3, 4} with title Dtitle
	end if
	return ans
end run

and a fun version that will move the Dialog to a random location, and wait 10 seconds and then Click the cancel button.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

on run xargs
	local proc, Dtitle, h, w, mywin, i
	if (class of xargs) = list then
		set {proc, Dtitle, w, h} to xargs
		tell application "System Events" to tell application process proc
			repeat until exists (window 1 whose title is Dtitle) --(window 1 whose subrole is "AXDialog")
				delay 0.05
			end repeat
			set mywin to window 1 whose title is Dtitle
			set position of mywin to {w, h}
			repeat with i from 10 to 0 by -1 -- ten second delay
				try
					title of mywin
				on error
					exit repeat
				end try
				delay 1
			end repeat
			if i = 0 then -- did time out
				try
					click button "Cancel" of mywin
				end try
			end if
		end tell
	else
		set cPath to quoted form of (POSIX path of (path to me))
		set {w, h} to getScreenSize()
		set {w, h} to {random number from 10 to (w - 350), random number from 30 to (h - 220)}
		set Dtitle to "List Chooser"
		do shell script "osascript " & cPath & " '" & (name of current application) & "' '" & Dtitle & "' " & w & " " & h & " &>/dev/null &"
		delay 0.1 -- give osascript time to load, helps with redraw issues
		set ans to choose from list {1, 2, 3, 4} with title Dtitle
	end if
	return ans
end run

on getScreenSize()
	local theScreen, theFrame
	set theScreen to current application's NSScreen's mainScreen()
	set theFrame to item 2 of theScreen's visibleFrame()
	return {item 1 of theFrame as integer, item 2 of theFrame as integer}
end getScreenSize

Yes, perfect! Thanks a lot also for for all inputs!

I found now a problem trying to run / positioning the dialog list when it is activated out of the Photos Application Process. How can your script be integrated here?

tell application "photos"

	set ans to choose from list {1, 2, 3, 4}
end tell

integrating it into application “System Event” it works fine.

Why is the ‘choose from list’ command inside a tell block for “photos”?

and how are you executing the script?

If running from Script Menu then it is mainly being run by osascript. This poses an issue where 2 osascript commands will be running, so we need a way to distinguish them.
I have a way to get the pid (unix process id) of the main one.

Here is a more robust version that can be run from the Script menu, hence it’s application will be osascript.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

on run xargs
	local proc, Dtitle, h, w, mywin, i
	if ((class of xargs) = list) and ((count xargs) > 0) then
		set {proc, Dtitle, w, h} to xargs
		tell application "System Events"
			set proc to item 1 of (processes whose unix id = proc)
			tell proc
				repeat with i from 10 to 0 by -1
					if exists (window 1 whose title is Dtitle) then exit repeat --(window 1 whose subrole is "AXDialog")
				end repeat
				if i = 0 then return -- timed out
				set mywin to window 1 whose title is Dtitle
				set position of mywin to {w, h}
				repeat with i from 3 to 0 by -1 -- ten second delay
					try
						title of mywin
					on error
						exit repeat
					end try
					delay 1
				end repeat
				if i ≠ 0 then return -- didn't time out
				try
					click button "Cancel" of mywin
				end try
			end tell
		end tell
	else
		set cPath to quoted form of (POSIX path of (path to me))
		set Dtitle to "List Chooser"
		set proc to getPID(DTitle)
		repeat 10 times
			set {w, h} to getScreenSize()
			set {w, h} to {random number from 10 to (w - 350), random number from 30 to (h - 220)}
			set cPath to quoted form of (POSIX path of (path to me))
			do shell script "osascript " & cPath & " '" & proc & "' '" & Dtitle & "' " & w & " " & h & " &>/dev/null &"
			delay 0.1
			set ans to choose from list {1, 2, 3, 4} with title Dtitle
		end repeat
	end if
	return ans
end run

on getScreenSize()
	local theScreen, theFrame
	set theScreen to current application's NSScreen's mainScreen()
	set theFrame to item 2 of theScreen's visibleFrame()
	return {item 1 of theFrame as integer, item 2 of theFrame as integer}
end getScreenSize

on getAllScreens()
	local scList
	set scList to {}
	set ans to paragraphs of (do shell script "defaults read /Library/Preferences/com.apple.windowserver | egrep  -w  '(LimitsWidth|LimitsHeight)'")
	repeat with c from 2 to (count ans) div 2 by 2
		set end of scList to {word 3 of item c of ans, word 3 of item (c - 1) of ans}
	end repeat
	return scList
end getAllScreens

on getPID(Ditle)
	local mName, osalist, pid
	set mName to name of current application
	set osalist to paragraphs of (do shell script "ps -ecwwo pid,comm,args | grep '" & mName & "'")
	set pid to 0
	repeat with i in osalist
		if mName is in i then
			if Dtitle is not in i then return (word 1 of i) as integer
		end if
	end repeat
	return false
end getPID

I edited the getPID() handler above to work better when run from osascript. It now uses the Dialog title, which was passed as an argument to the second osascript, as a method to distinguish between them.

If the main script is not being run from the Script Menu (hence osascript) then I have a much faster getPID() handler like below…

on getPID() -- fastest
	local currApp, apps, PIDs
	set currApp to name of current application
	tell application "System Events" to set {apps, PIDs} to {name, unix id} of processes
	repeat with i from 1 to count apps
		if (item i of apps) = currApp then
			return item i of PIDs
		end if
	end repeat
end getPID

I tested Robert’s suggestion and it works great. An ingenious solution.

It should be noted that Shane’s Myriad Tables Lib script library is a solution that might be considered. I’ve included below a simple example of the code and resulting dialog. The script library can be found here.

There are several restrictions on the use of the Myriad Tables Lib:

Important: Scripts using Myriad Tables cannot be edited in Script Editor in Mojave and later because of new security settings, so you need to use Script Debugger, version 7 or later. You also cannot use it in scripts run from Apple’s Scripts menu, but they run fine from FastScripts.app’s menu.

I use this method to have my scripts be able to control themselves when dialogs appear all the time

Ok, the problem about the tell block of Photos is as follows. My script performes tasks dedicated on selected fotos in “Photos” (depending on the choise of the “Dialog List” with different actions). It needs to be guaranteed, while using the script, that the selection of fotos in the background stays unchanged (to avoid misusage, as the script captured only the situation at the beginning with at startup and not continiously). I use set SelectedPhotos to selection .

Running the dialog list out of the tell block of Photos ssems to guarantee this, as Photos is therefore blocked in the background and selectiosn can’t be changed.

From where to run the script?
I saved the script as “Fast action” (I don’t know the official expression in english) out of Automator and it is saved in the ‘services folder’. From there it is available to run out of the Services Menu from Photos (or via a shortcut linked to it). This makes it quite handy for me for fast usage.

So the original idea was, to automatically place the dialog box not in the middle (where it is normally in the way) but somewhere on the side.

I usually put scripts for Individual apps in the special folder Apple has for each App in location StartupDisk/Users//Library/Scripts/Applications.
Inside this folder you can create a Folder for each application you want to have scripts for.
Name the folder exactly the same as the Application, so for Photos app the folder would be named “Photos”

These scripts then show under the Script Menu if you have these items checked in the preferences of Script Editor like so

My Script Menu looks like so…
Screenshot 2024-02-03 at 1.42.51 PM

Notice the ‘Finder Scripts’ section. This is because the Finder was my frontmost app at the moment.

I personally hate Automator, I use raw scripting for everything

1 Like

Thanks for the tip I didn’t know so far…
Normally I don’t use Automator. But in this case I want to activat a script via shortcut which for me is very handy when working in Photos. (I haven’t figured out how to assign shortcuts for scripts in the script menu). I only know the way to save it as “quick action” out of Automator, then assign a shortcut to it in the system preferences at “Services”. I found it a fast and handy way to activate it when using it often working with Photos.

Thanks robertfern for the detailed script which is excelent solution itself (When not run out of a tell block of photos when I get it right?).

Thanks peavine for your hint using the Myriad Tables lib. I might give it a go later on as I don’t use Script Debugger right now. When I got it right this would be a solution to run the dialog box directly out of the photos tell block?

Borima. The limitations on the use of Myriad Tables are significant, which is unfortunate because it does so many things so well. In retrospect, it’s probably not a good solution for you.

FWIW, I’ve included a simple example of how I might use it with the Photos app. This worked when run by way of FastScripts on my Sonoma computer, but it did not work when run as an AppleScript app or by way of the AppleScript menu.

use AppleScript version "2.4"
use scripting additions
use script "Myriad Tables Lib" version "1.0.13"

tell application "Photos"
	activate
	set theResponse to showDialog() of me
	-- do other stuff
end tell

on showDialog()
	set theTable to make new table with data {"One", "Two", "Three", "Four"} with prompt "Dialog prompt" with title "Dialog Title" initially selected rows {1}
	modify table theTable initial position {300, 400} OK button name "Yes" extra button name "Maybe" with alternate backgrounds
	set theValues to display table theTable
	return values selected of theValues
end showDialog