3x3 Matrix Bounds

Hi,
while sorting files hoarded over the years, thought I cud arrange finder windows (cud be other apps too) on one of the screen (I have two)

First Take, which works


tell application "Finder" to set {a, b, c, d} to bounds of window of desktop
--3x3 Matrix
	set nCol to 3
	set nRow to 3
	set w to (c - a) / nCol
	set h to (d - b) / nRow

set win1 to {(a + 0 * w), (b + 0 * h), (a + 1 * w), (b + 1 * h)} --LeftTop
	set win2 to {(a + 0 * w), (b + 1 * h), (a + 1 * w), (b + 2 * h)} --LeftMid
	set win3 to {(a + 0 * w), (b + 2 * h), (a + 1 * w), (b + 3 * h)} --LeftBottom
	
	set win4 to {(a + 1 * w), (b + 0 * h), (a + 2 * w), (b + 1 * h)} --MiddleTop
	set win5 to {(a + 1 * w), (b + 1 * h), (a + 2 * w), (b + 2 * h)} --MiddleMid
	set win6 to {(a + 1 * w), (b + 2 * h), (a + 2 * w), (b + 3 * h)} --Middle
	
	set win7 to {(a + 2 * w), (b + 0 * h), (a + 3 * w), (b + 1 * h)} --RightTop
	set win8 to {(a + 2 * w), (b + 1 * h), (a + 3 * w), (b + 2 * h)} --RightMid
	set win9 to {(a + 2 * w), (b + 2 * h), (a + 3 * w), (b + 3 * h)} --RightBottom

Then I tried this, which generates the bounds.


tell application "Finder" to set {a, b, c, d} to bounds of window of desktop
--3x3 Matrix
	set nCol to 3
	set nRow to 3
	set w to (c - a) / nCol
	set h to (d - b) / nRow
set Hc to "1"
repeat until Hc = nCol + 1
	set Wc to "1"
	repeat until Wc = nRow + 1
		set winBound to {(a + (Hc - 1) * w), (b + (Wc - 1) * h), (a + Hc * w), (b + Wc * h)}
		-- do something with winBound
		
		set Wc to Wc + 1
	end repeat
	set Hc to Hc + 1
end repeat

Just wondering if it cud be written better,
cud take into account the "useable " area of the screen,
Assign these bounds to existing Finder windows.
I cant figure out how to count windows 1, windows 2 etc and assign them to generated bounds
Cheers

Thanks peavine, i wud try your script. Meanwhile plz have a look at another try
This assumes LeftTop window = 1, LeftMid = 2, MiddleMid=5 … RightBottom=9


-- LeftBottom wud be 3
winBounds(GetColRow("3") of me)

on GetColRow(winNo)
	if winNo = 0 then
		return
	else if winNo ≤ 3 then
		set Hc to "1"
		if winNo is "1" then
			set Wc to "1"
			return {Hc, Wc}
		else if winNo is "2" then
			set Wc to "2"
			return {Hc, Wc}
		else if winNo is "3" then
			set Wc to "3"
			return {Hc, Wc}
		end if
	else if winNo ≤ 6 then
		set Hc to "2"
		if winNo is "4" then
			set Wc to "1"
			return {Hc, Wc}
		else if winNo is "5" then
			set Wc to "2"
			return {Hc, Wc}
		else if winNo is "6" then
			set Wc to "3"
			return {Hc, Wc}
		end if
	else
		set Hc to "3"
		if winNo is "1" then
			set Wc to "7"
			return {Hc, Wc}
		else if winNo is "2" then
			set Wc to "8"
			return {Hc, Wc}
		else if winNo is "9" then
			set Wc to "3"
			return {Hc, Wc}
		end if
	end if
end GetColRow

on winBounds(GetColRow)
	set {a, b, c, d} to {1920, 0, 3840, 1080}
	set w to (c - a) / 3
	set h to (d - b) / 3
	set Hc to item 1 of GetColRow
	set Wc to item 2 of GetColRow
	set winBound to {(a + (Hc - 1) * w), (b + (Wc - 1) * h), (a + Hc * w), (b + Wc * h)}
	return winBound
end winBounds

Sorry–my mistake. I’ll try your script.

One208. I tested the second script in post 1, and, after adding the necessary Finder code and making a few other edits, it works well.

tell application "Finder"
	activate
	set {a, b, c, d} to bounds of window of desktop
	set b to b + 25 -- adjust for menu height
end tell

set nCol to 3
set nRow to 3
set w to ((c - a) / nCol) as integer
set h to ((d - b) / nRow) as integer

set theBounds to {}
repeat with i from 1 to nCol
	repeat with j from 1 to nRow
		set winBound to {a + ((i - 1) * w), b + ((j - 1) * h), a + (i * w), b + (j * h)}
		set end of theBounds to winBound
	end repeat
end repeat

tell application "Finder"
	repeat with i from 1 to (count Finder windows)
		set bounds of Finder window i to (item i of theBounds)
	end repeat
end tell

Your script does not consider the dock height or width (if the dock is visible). To fix this, I think you would have to use the visible screen area as returned by the following:

use framework "Foundation"
use scripting additions

set theFrame to current application's NSScreen's screens()'s firstObject()'s visibleFrame() as list
-- returns {{69.0, 0.0}, {1851.0, 1055.0}} on my computer with dock side-aligned

Thanks peavine, I am happy I cud write a working script :slight_smile:


--change if Finder window count was less then 9
tell application "Finder"
	set n to count of windows
	repeat with i from 1 to n
		set bounds of Finder window i to (item i of theBounds)
	end repeat
end tell

One208. Your script works extremely well. I’ll be interested to see how you edit the script to account for dock height or width.

@peavine, for the time being, I think I am going to copy
https://www.macscripter.net/viewtopic.php?id=46336


use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
set myScreenID to 188975774 
set screensInfo to getUsableScreenBounds()
-- →{{screenID:188975774, usableBounds:{0, 23, 1920, 1017}}, {screenID:188815381, usableBounds:{1920, 0, 3840, 1080}}}
repeat with thisScreen in screensInfo
	if (thisScreen's screenID is myScreenID) then
		set {a, b, c, d} to thisScreen's usableBounds
		exit repeat
	end if
end repeat
set nCol to 3
set nRow to 3
set w to (c - a) / nCol
set h to (d - b) / nRow
set Hc to "1"
set theBounds to {}
repeat until Hc = nCol + 1
	set Wc to "1"
	repeat until Wc = nRow + 1
		set winBound to {(a + (Hc - 1) * w), (b + (Wc - 1) * h), (a + Hc * w), (b + Wc * h)}
		set end of theBounds to winBound
		set Wc to Wc + 1
	end repeat
	set Hc to Hc + 1
end repeat

tell application "Finder"
	set n to count of windows
	repeat with i from 1 to n
		set bounds of Finder window i to (item i of theBounds)
	end repeat
end tell
--================================================================
--» HANDLER 
--================================================================
on getUsableScreenBounds()
	set |⌘| to current application
	set theResult to {}
	set theScreens to |⌘|'s class "NSScreen"'s screens()
	repeat with thisScreen in theScreens
		set screenID to ((thisScreen's deviceDescription())'s valueForKey:("NSScreenNumber")) as integer
		set wholeFrame to thisScreen's frame()
		set visibleFrame to thisScreen's visibleFrame()
		
		-- In High Sierra, the frame rects are returned as lists instead of records, but the functions below work with either.
		set x1 to (|⌘|'s NSMinX(visibleFrame)) as integer
		-- The y origin in NSScreen is at the bottom of the screen. It needs to be converted to an origin at the top for AS.
		set y1 to ((|⌘|'s NSMaxY(wholeFrame)) - (|⌘|'s NSMaxY(visibleFrame))) as integer
		set x2 to (|⌘|'s NSMaxX(visibleFrame)) as integer
		set y2 to (y1 + (|⌘|'s NSHeight(visibleFrame))) as integer
		set end of theResult to {screenID:screenID, usableBounds:{x1, y1, x2, y2}}
	end repeat
	
	return theResult
end getUsableScreenBounds
--» End of Handler ===================================================