New problem, why is this so slow?

G’day

This first script executes quite fast, 7 seconds for 212 items, but the full script is extraordinarily slow. Anyone see why? The problem is in the ‘Select keepSelection’ line. It seems to lock up and time out.

Select any window with lots of icons, select all the icons, and run the full script to see the delay.

Any thoughts appreciated.

Regards

Santa


tell application "Finder"
	set pta to path to applications folder
	open pta
	select every item of pta
	set x to current date
	set ptw to container of item 1 of pta
	set keepSelection to selection as alias list
	close ptw
	open ptw
	select keepSelection
	say (current date) - x as text
end tell


--  ****************************
--  * Not Copyright, Brian Christmas     *
--  *                                                    *
--  *   From the Sunny Land of Oz        *
--  *             Version 2.0                      *
--  *             21 Jan 11                        *
--  *                                                    *
--  *        OzSanta@gmail.com             *
--  ****************************

-- AID OR Automatic Icon Distributor

-- Qsort routine from MacScripter
-- http://bbs.applescript.net/viewtopic.php?id=17340

-- Thanks to Yvan Koenig for the routine that traps
-- the Window of the Desktop that holds selected icons

-- This script works best if some approximate 
-- organizing is done first, otherwise extra columns
-- may be added, especially on horizontal single lines,
-- or columns left empty if you've left vertical gaps.

-- Also note that if insufficient side margins are not allowed for when arranging a windows icons,
-- the Finder may 'shake' the window from side to side, thereby altering the icon placement.

-- It's particularly important to have a wide margin on the left when arranging,
-- otherwise the left column may not get arranged correctly, & need a second pass.

-- Feedback appreciated, especially suggestions to speed this up.

-- *******************************
-- **** Set this as minimum amount ****
-- ****   allowed between columns     ****
-- *******************************
property seedValue : 100
-- *******************************
-- **** Set this as minimum amount ****
-- ****          of icons to offer             ****
-- ****          alphabet sorting            ****
-- *******************************
property AlphabetMin : 20
-- *******************************
-- **** Set this to true to vertically    ****
-- **** stagger labels that are closer  ****
-- **** than seedvalue + 40 pixles    ****
-- *******************************
property staggered : false -- set to true or false
property StaggeredCount : 0
property we_are_on_desktop : false
property IconList : {}
property IconPositions : {}
property overlapFlag : false
property FoundDisk : true
property thelist : {}
property KeepSelection : {}
property templist : {}
property currX : 0
property SmallestY : 0
property iconspacing : 0
property XYlist : {}
property theWindow : {}


on run
	tell application "Finder"
		set KeepDate to current date
		set currX to 0
		set LargestY to 0
		set SmallestY to 0
		set SmallestX to 0
		set LargestX to 0
		set overlapFlag to 0
		set Xdifflist to {}
		set ydiffList to {}
		set columnCount to {}
		set XYlist to {}
		set we_are_on_desktop to false
		--try
		
		try
			set tt to 0
			set ttt to 0
			set theWindow to window 1 as alias
			tell application "System Events" to tell process "Finder"
				set t to value of static text 1 of theWindow
				if word 4 of t = "selected" then
					set tt to word 1 of t as number
					set ttt to word 3 of t as number
				end if
			end tell
		end try
		if tt > 300 and tt < 351 then
			display dialog "There are " & tt & " items selected, out of " & ttt & ", and 'cause the Finder is very, very slow with large numbers of icons in windows, I'm giving you the chance to Cancel." buttons {"Continue anyway", "Cancel"}
			if the button returned of the result = "Cancel" then return
		end if
		if tt > 350 then
			display dialog "There are too many items, (" & ttt & "), 'cause the Finder is very, very slow with large numbers of icons in windows." & return & return & "So, I'm quitting!"
			return
		end if
		set KeepSelection to the selection as alias list
		set ListLength to count of KeepSelection
		if ListLength = 0 then
			display dialog "There are no icons selected." & return & return & "Try selecting some, and running the script again." buttons {"OK"}
			return
		end if
		if ListLength = 1 then
			display dialog "There is only one icon selected." & return & return & "Try selecting more, and running the script again." buttons {"OK"}
			return
		end if
		set FoundDisk to false
		set xx to ListLength
		repeat with x from 1 to ListLength
			if kind of item x of KeepSelection as text ≠ "Volume" then
				set xx to x
				if FoundDisk then exit repeat
			else
				set FoundDisk to true
				set KeepDisk to item x of KeepSelection
				if xx < ListLength then exit repeat
			end if
		end repeat
		set ThisItem to item xx of KeepSelection
		set ptw to container of (ThisItem)
		if (count of windows) > 0 then
			try
				if name of window 1 = "Desktop" then
					tell application "Finder"
						activate
						set windName to get localized string "N5"
					end tell
					
					tell application "System Events" to tell application process "Finder" to tell menu bar 1 to tell menu bar item 7 to tell menu 1
						set noemi to (name of every menu item)
						if (noemi contains windName) then
							set windStatus to false
							repeat with i from 1 to count of noemi
								try (* to get rid of "missing value" *)
									if (name of menu item i is windName) and (value of attribute "AXMenuItemMarkChar" of menu item i is not "") then
										set windStatus to true
										exit repeat
									end if
								end try
							end repeat
							
						else
							set windStatus to false
						end if
					end tell
					if windStatus then
						tell application "Finder"
							try
								set EnclosingFolder to container of ThisItem as string
								close window "Desktop"
							end try
							display dialog "A Window belonging to the Desktop was frontmost, and you have selected Icons in it, and tried to organize them." & return & return & "Doing so may seriously disrupt your actual Desktop Icon arrangement." & return & return & "If you wish to organize any Desktop icons, please select them on the Desktop itself." buttons {"So, I've stopped it."}
							try
								open EnclosingFolder
							end try
						end tell
						return
					end if
				end if
			end try
		end if
		--- ARE WE ON THE DESKTOP?
		try
			set we_are_on_desktop to ((container of ThisItem as alias) is (path to desktop folder))
		on error
			set we_are_on_desktop to (kind of ThisItem as text = "Volume") --< only Volume icons selected
		end try
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			delay 0.2
			try
				activate
			end try
			select disk KeepDisk
			close window 1
		end if
		-- make array of positions
		if we_are_on_desktop then
			repeat with ThisItem from 1 to ListLength
				set temp to desktop position of item ThisItem of KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		else
			repeat with ThisItem from 1 to ListLength
				set temp to position of item ThisItem of KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		end if
		--say (current date) - KeepDate as text
		set IconPositions to XYlist
		set AlphaFlag to false
		-- Heaps of icons? then ask!
		if ListLength > (AlphabetMin - 1) then
			display dialog " there are " & ListLength & " icons selected." & return & return & "Do you want to sort them alphabetically or normally?" & return & return & "(it takes a while with large numbers)" buttons {"Alphabetically please", "Normally thanks", "Cancel"}
			set AlphaFlag to (the button returned of the result is "Alphabetically please")
		end if
		if we_are_on_desktop then
			set theTotal to count of items of desktop
			set IconSize to icon size of icon view options of window of desktop
			set ArrangementValue to arrangement of icon view options of window of desktop
		else
			set TheCurrentView to current view of window 1
			if TheCurrentView ≠ icon view then
				set the current view of window 1 to icon view
				display dialog "I have reset the view of the window to 'icon view'. Do you wish to proceed?" buttons {"No", "Proceed"}
				if the button returned of the result = "No" then
					set the current view of window 1 to TheCurrentView
					return
				end if
			end if
			set theTotal to count of items of window 1
			set IconSize to icon size of icon view options of window 1
			set ArrangementValue to (arrangement of (icon view options of window 1))
		end if
		if ArrangementValue = not arranged then set ArrangementValue2 to "not arranged"
		if ArrangementValue = snap to grid then set ArrangementValue2 to "snap to grid"
		if ArrangementValue = arranged by name then set ArrangementValue2 to "arranged by name"
		if ArrangementValue = arranged by modification date then set ArrangementValue2 to "arranged by modification date"
		if ArrangementValue = arranged by creation date then set ArrangementValue2 to "arranged by creation date"
		if ArrangementValue = arranged by size then set ArrangementValue2 to "arranged by size"
		if ArrangementValue = arranged by kind then set ArrangementValue2 to "arranged by kind"
		if ArrangementValue = arranged by label then set ArrangementValue2 to "arranged by label"
		
		set AddendumText to ""
		if ListLength < theTotal then set AddendumText to "You have only selected " & ListLength & " of " & theTotal & " items. The new arrangement mightn't look good because the extra icons may end up all over the place." & return & return
		if ArrangementValue2 ≠ "not arranged" then
			display dialog "The window of the selection has a current arrangement of '" & ArrangementValue2 & "'. " & return & return & "Setting the window to 'not arranged' may have unexpected consequences for the icon arrangement." & AddendumText & "Do you want to proceed?" & return & return & "(You will be given a 'restore' option)." buttons {"Proceed", "No thanks"}
			if button returned of the result = "No thanks" then return
		end if
		if ArrangementValue2 ≠ "not arranged" then
			if we_are_on_desktop then
				set arrangement of icon view options of window of desktop to not arranged
			else
				try
					set (arrangement of icon view options of window 1) to not arranged
				on error errmsg
					display dialog errmsg
				end try
			end if
		end if
		my Qsort(Xdifflist, 1, (length of Xdifflist))
		my Qsort(ydiffList, 1, length of ydiffList)
		set LargestX to last item of Xdifflist
		set SmallestX to first item of Xdifflist
		set LargestY to last item of ydiffList
		set SmallestY to first item of ydiffList
		--say (current date) - KeepDate as text
		
		if we_are_on_desktop then
			set seedValueadd to ((label position of icon view options of window of desktop) = right)
		else
			set seedValueadd to ((label position of icon view options of window 1) = right)
		end if
		
		-- If text is on right, double the minimum spacing
		if seedValueadd = true then
			set seedValue to seedValue * 2
			set staggered to false --<-- no need to stagger them
		end if
		-- Now the guessing part, what to ListLength as column spacing?
		if IconSize > seedValue then set seedValue to IconSize
		set setX to seedValue
		repeat with x from ((length of Xdifflist) - 1) to 1 by -1
			set diff to ((item (x + 1) of Xdifflist) - (item x of Xdifflist))
			if (diff > seedValue - 1) then set setX to diff
		end repeat
		--Now, set width between columns
		
		-- SPECIAL CASE : Roughly all on one horizontal line, then spread 'em evenly, else
		if LargestY - SmallestY < 60 and length of Xdifflist > 1 then
			set columnSpaces to (LargestX - SmallestX) div (((LargestX - SmallestX) div ((length of Xdifflist) - 1)))
		else
			set columnSpaces to ((LargestX - SmallestX + (setX / 2)) div setX)
		end if
		--Only 1 column? then set columnSpace to seedvalue
		if columnSpaces = 0 then
			set ColumnWidth to seedValue
			set columnSpaces to 1
		else
			if columnSpaces = 1 and (LargestX - SmallestX) < seedValue * 2 then
				set ColumnWidth to (LargestX - SmallestX)
			else
				set ColumnWidth to (LargestX - SmallestX) / columnSpaces
				if ColumnWidth < seedValue then set ColumnWidth to seedValue
				-- Roughly all on one horizontal line, then spread 'em evenly
				if LargestY - SmallestY < 60 then set ColumnWidth to (LargestX - SmallestX) / columnSpaces
			end if
		end if
		if staggered and columnSpaces > 0 then set staggered to ColumnWidth < (seedValue + 40)
		if staggered and columnSpaces > 1 then set LargestY to LargestY - 20
		set columnCount to columnSpaces + 1
		
		set columnCountStore to 0
		set columnXstore to {0, 0}
		repeat with x from 1 to columnSpaces
			set end of columnXstore to {0, 0}
			set columnCountStore to columnCountStore & 0
		end repeat
		repeat with x from 1 to columnCount
			set minX to SmallestX + ((x - 1) * ColumnWidth) - (ColumnWidth / 2)
			set MaxX to SmallestX + ((x - 1) * ColumnWidth) + (ColumnWidth / 2)
			set item x of columnXstore to {minX, MaxX}
		end repeat
		repeat with ThisItem in KeepSelection
			if we_are_on_desktop then
				set temp to desktop position of ThisItem
			else
				set temp to position of ThisItem
			end if
			repeat with x from 1 to columnCount
				set minX to item 1 of item x of columnXstore
				set MaxX to item 2 of item x of columnXstore
				set tempX to item 1 of temp
				-- if icon falls in the range of column, add it up
				if ((tempX = minX) or (tempX > minX)) and (tempX < MaxX) then
					set item x of columnCountStore to ((item x of columnCountStore) + 1)
				end if
			end repeat
		end repeat
		--say (current date) - KeepDate as text
		if AlphaFlag then --> Alphabet arrange set
			set iconspacing to (LargestY - SmallestY) / ((ListLength / columnCount) div 1)
		else
			
			-- Now find Column with largest number of icons
			
			set maxCount to 2 ---> to avoid division by zero if only one row
			repeat with x from 1 to number of items in columnCountStore
				if item x of columnCountStore > maxCount then
					set maxCount to item x of columnCountStore
				end if
			end repeat
			set iconspacing to ((LargestY - SmallestY) / (maxCount - 1))
		end if
		--say (current date) - KeepDate as text
		if AlphaFlag then
			my SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
		else
			-- Now place Icons
			-- Loop ColumnCount times....
			repeat with MoveColumns from 1 to columnCount
				set minX to SmallestX + ((MoveColumns - 1) * ColumnWidth) - (ColumnWidth / 2)
				set MaxX to SmallestX + ((MoveColumns - 1) * ColumnWidth) + (ColumnWidth / 2)
				
				set templist to {}
				repeat with ThisItem from 1 to number of items in XYlist
					set temp to item ThisItem of XYlist
					set tempX to item 1 of temp
					if (((tempX = minX) or (tempX > minX)) and ((tempX < MaxX) or (tempX = MaxX))) then
						--Build list of icon XY positions in column
						set end of templist to tempX
						set end of templist to item 2 of temp
					end if
				end repeat
				-- This is the X value of the column
				set columnX to SmallestX + ((MoveColumns - 1) * ColumnWidth)
				--
				-- Now go and shift a column of the little bastards around!
				--
				my ArrangeColumn(templist, columnX, SmallestY, iconspacing, XYlist)
			end repeat
		end if
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			delay 0.2
			try
				activate
			end try
			select disk KeepDisk
			close window 1
		end if
		if not we_are_on_desktop then
			close ptw
			open ptw
		end if
	end tell
	--say (current date) - KeepDate as text
	tell application "Finder"
		if we_are_on_desktop then
			repeat with SelectDisk in KeepSelection
				tell application "System Events" to tell process "Finder"
					try
						select image (name of SelectDisk) of group 1 of scroll area 1
					end try
				end tell
			end repeat
		else
			
			 with timeout of 600 seconds
				select KeepSelection -- <<<<<<<<<<<<<<<<<<<<<<<<<<< The problem is here!
			end timeout 
		end if
		--say (current date) - KeepDate as text
		display dialog "Restore?" & return & return & "Is this arrangement satisfactory?" buttons {"Yes", "No"}
		if button returned of the result = "No" then
			if we_are_on_desktop then
				repeat with x from 1 to ListLength
					set desktop position of item x of KeepSelection to item x of IconPositions
				end repeat
				if FoundDisk then --< there is at least one disk in the mix, so restart Finder
					quit
					delay 0.2
					try
						activate
					end try
					select disk KeepDisk
					close window 1
				end if
				if ArrangementValue2 ≠ "not arranged" then set arrangement of icon view options of window of desktop to ArrangementValue
			else
				if ArrangementValue2 ≠ "not arranged" then
					set (arrangement of icon view options of window 1) to ArrangementValue
				else
					repeat with x from 1 to ListLength
						set position of item x of KeepSelection to item x of IconPositions
					end repeat
				end if
			end if
			if not we_are_on_desktop then
				close ptw
				open ptw
			end if
		end if
		(*on error errmsg
			display dialog errmsg
		end try*)
		say "finished"
	end tell
end run

-- =============================================================

on ArrangeColumn(templist, currX, SmallestY, iconspacing, XYlist)
	tell application "Finder"
		try
			-- Start with a Y seed position, to overcome 
			-- problem with 1 entry not seen as an item
			set ylist to {0}
			--
			-- Now make list of Y positions
			repeat with Cycle from 1 to number of items in XYlist
				set temp to item Cycle of XYlist
				set ThisItem to item Cycle of KeepSelection
				if temp is in templist then
					set ylist to ylist & item 2 of temp
				end if
			end repeat --
			-- Sort Y positions
			my Qsort(ylist, 1, length of ylist)
			--
			-- Now position each
			--display dialog number of items in XYlist as text
			repeat with Cycle from 1 to number of items in XYlist
				set thisItemTwo to item Cycle in KeepSelection
				set temp to item Cycle of XYlist
				if we_are_on_desktop then
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set desktop position of thisItemTwo to {currX, currY + StaggeredCount}
					end if
				else
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set position of thisItemTwo to {currX, currY + StaggeredCount}
					end if
				end if
			end repeat
			if staggered then
				if StaggeredCount = 0 then
					set StaggeredCount to 20
				else
					set StaggeredCount to 0
				end if
			end if
		on error errmsg
			display dialog errmsg
		end try
	end tell
end ArrangeColumn

on SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
	
	tell application "Finder"
		try
			set templist to {}
			-- First, sort list of icons alphabetically
			set xx to length of KeepSelection
			repeat with x from 1 to xx
				set end of templist to name of item x of KeepSelection
			end repeat
			my Qsort(templist, 1, xx)
			set iconPos to 1
			set Xwidth to LargestX - SmallestX + ColumnWidth
			if staggered then set staggered to ColumnWidth < (seedValue + 40)
			repeat with ThisItem in KeepSelection
				set tempName to name of ThisItem
				repeat with mainCount from 1 to xx
					if tempName = item mainCount of templist then
						set farRightX to ((mainCount - 1) * ColumnWidth)
						set numberofRows to ((farRightX) / (Xwidth)) div 1
						set Xposition to SmallestX + (farRightX - (numberofRows * Xwidth))
						set yposition to SmallestY + ((numberofRows) * iconspacing)
						set columntemp to (((Xposition - SmallestX) / ColumnWidth) + 0.5) div 1
						if staggered then
							set StaggeredCount to 0
							if (columntemp mod 2) = 1 then set StaggeredCount to 20
						end if
						
						if we_are_on_desktop then
							set desktop position of ThisItem to {Xposition, yposition + StaggeredCount}
						else
							set position of ThisItem to {Xposition, yposition + StaggeredCount}
						end if
						exit repeat
					end if
				end repeat
			end repeat
		end try
	end tell
end SortbyAlphabet

to Qsort(array, leftEnd, rightEnd) -- Hoare's QuickSort Algorithm
	script A
		property L : array
	end script
	set {i, j} to {leftEnd, rightEnd}
	set v to item ((leftEnd + rightEnd) div 2) of A's L -- pivot in the middle
	repeat while (j > i)
		repeat while (item i of A's L < v)
			set i to i + 1
		end repeat
		repeat while (item j of A's L > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell A's L to set {item i, item j} to {item j, item i} -- swap
			set {i, j} to {i + 1, j - 1}
		end if
	end repeat
	if (leftEnd < j) then Qsort(A's L, leftEnd, j)
	if (rightEnd > i) then Qsort(A's L, i, rightEnd)
end Qsort


Model: 27" iMac
Browser: Safari 533.19.4
Operating System: Mac OS X (10.6)

G’day

Took a while, but I found that accessing the .DS_Store file in the folder was to blame. Once the icons were shifted, the access to that file slowed to a crawl, and was exponentially slowing down based on icon numbers.

I wrote a script to delete the .DS.Store, and re-launch the folder to re-build it, and it’s near instantaneous in selecting the selected files/folders.

A short script…


tell application "Finder"
	try
		set t to container of (item 1 of ((items of window 1) as alias list)) as alias as text
		set tt to (t & ".DS_Store") as text as alias
		set name of tt to "   temp1234567890"
		move ((t & "   temp1234567890") as text) to trash
		quit
		delay 0.2
		try
			activate
		end try
	end try
end tell

and the full finished (I hope!) script if anyone would like to trial and comment on it, thanks…


--  ****************************
--  * Not Copyright, Brian Christmas     *
--  *                                                    *
--  *   From the Sunny Land of Oz        *
--  *             Version 2.0                      *
--  *             21 Jan 11                        *
--  *                                                    *
--  *        OzSanta@gmail.com             *
--  ****************************

-- AID or Automatic Icon Distributor

-- Minimum recommended System 10.6.6

-- Qsort routine from MacScripter
-- http://bbs.applescript.net/viewtopic.php?id=17340

-- Thanks to Yvan Koenig for the routine that traps
-- the Window of the Desktop that holds selected icons

-- This script works best if some approximate 
-- organizing is done first, otherwise extra columns
-- may be added, especially on horizontal single lines,
-- or columns left empty if you've left vertical gaps.

-- Feedback appreciated, especially suggestions to speed this up.

-- *******************************
-- **** Set this as minimum amount ****
-- ****   allowed between columns     ****
-- *******************************
property seedValue : 100
-- *******************************
-- **** Set this as minimum amount ****
-- ****          of icons to offer             ****
-- ****          alphabet sorting            ****
-- *******************************
property AlphabetMin : 20
-- *******************************
-- **** Set this to true to vertically    ****
-- **** stagger labels that are closer  ****
-- **** than seedvalue + 40 pixles    ****
-- *******************************
property staggered : false -- set to true or false
property StaggeredCount : 0
property we_are_on_desktop : false
property IconList : {}
property IconPositions : {}
property overlapFlag : false
property FoundDisk : true
property thelist : {}
property KeepSelection : {}
property templist : {}
property currX : 0
property SmallestY : 0
property iconspacing : 0
property XYlist : {}
property theWindow : {}
property ttt : 0

on run
	tell application "Finder"
		set KeepDate to current date
		set currX to 0
		set LargestY to 0
		set SmallestY to 0
		set SmallestX to 0
		set LargestX to 0
		set overlapFlag to 0
		set Xdifflist to {}
		set ydiffList to {}
		set columnCount to {}
		set XYlist to {}
		set we_are_on_desktop to false
		--try
		
		try
			set tt to 0
			set ttt to 0
			set theWindow to window 1
			tell application "System Events" to tell process "Finder"
				set t to value of static text 1 of window 1
				if word 4 of t = "selected" then
					set tt to word 1 of t as number
					set ttt to word 3 of t as number
				end if
			end tell
		end try
		if tt > 500 and tt < 701 then
			display dialog "There are " & tt & " items selected, out of " & ttt & ", and 'cause the Finder is very, very slow with large numbers of icons in windows, I'm giving you the chance to Cancel." buttons {"Continue anyway", "Cancel"}
			if the button returned of the result = "Cancel" then return
		end if
		if tt > 700 then
			display dialog "There are too many items, (" & ttt & "), 'cause the Finder is very, very slow with large numbers of icons in windows." & return & return & "So, I'm quitting!"
			return
		end if
		set my KeepSelection to the selection as alias list
		set ListLength to count of my KeepSelection
		if ListLength = 0 then
			display dialog "There are no icons selected." & return & return & "Try selecting some, and running the script again." buttons {"OK"}
			return
		end if
		if ListLength = 1 then
			display dialog "There is only one icon selected." & return & return & "Try selecting more, and running the script again." buttons {"OK"}
			return
		end if
		set FoundDisk to false
		set xx to ListLength
		repeat with x from 1 to ListLength
			if kind of item x of my KeepSelection as text ≠ "Volume" then
				set xx to x
				if FoundDisk then exit repeat
			else
				set FoundDisk to true
				set KeepDisk to item x of my KeepSelection
				if xx < ListLength then exit repeat
			end if
		end repeat
		set ThisItem to item xx of my KeepSelection
		set ptw to container of (ThisItem)
		if (count of windows) > 0 then
			try
				if name of window 1 = "Desktop" then
					tell application "Finder"
						activate
						set windName to get localized string "N5"
					end tell
					
					tell application "System Events" to tell application process "Finder" to tell menu bar 1 to tell menu bar item 7 to tell menu 1
						set noemi to (name of every menu item)
						if (noemi contains windName) then
							set windStatus to false
							repeat with i from 1 to count of noemi
								try (* to get rid of "missing value" *)
									if (name of menu item i is windName) and (value of attribute "AXMenuItemMarkChar" of menu item i is not "") then
										set windStatus to true
										exit repeat
									end if
								end try
							end repeat
							
						else
							set windStatus to false
						end if
					end tell
					if windStatus then
						tell application "Finder"
							try
								set EnclosingFolder to container of ThisItem as string
								close window "Desktop"
							end try
							display dialog "A Window belonging to the Desktop was frontmost, and you have selected Icons in it, and tried to organize them." & return & return & "Doing so may seriously disrupt your actual Desktop Icon arrangement." & return & return & "If you wish to organize any Desktop icons, please select them on the Desktop itself." buttons {"So, I've stopped it."}
							try
								open EnclosingFolder
							end try
						end tell
						return
					end if
				end if
			end try
		end if
		--- ARE WE ON THE DESKTOP?
		try
			set we_are_on_desktop to ((container of ThisItem as alias) is (path to desktop folder))
		on error
			set we_are_on_desktop to (kind of ThisItem as text = "Volume") --< only Volume icons selected
		end try
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			delay 0.2
			try
				activate
			end try
			select disk KeepDisk
			close window 1
		end if
		-- make array of positions
		if we_are_on_desktop then
			repeat with ThisItem from 1 to ListLength
				set temp to desktop position of item ThisItem of my KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		else
			repeat with ThisItem from 1 to ListLength
				set temp to position of item ThisItem of my KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		end if
		--say (current date) - KeepDate as text
		set IconPositions to XYlist
		set AlphaFlag to false
		-- Heaps of icons? then ask!
		if ListLength > (AlphabetMin - 1) then
			display dialog " there are " & ListLength & " icons selected." & return & return & "Do you want to sort them alphabetically or normally?" & return & return & "(it takes a while with large numbers)" buttons {"Alphabetically please", "Normally thanks", "Cancel"}
			set AlphaFlag to (the button returned of the result is "Alphabetically please")
		end if
		if we_are_on_desktop then
			set theTotal to count of items of desktop
			set IconSize to icon size of icon view options of window of desktop
			set ArrangementValue to arrangement of icon view options of window of desktop
		else
			set TheCurrentView to current view of window 1
			if TheCurrentView ≠ icon view then
				set the current view of window 1 to icon view
				display dialog "I have reset the view of the window to 'icon view'. Do you wish to proceed?" buttons {"No", "Proceed"}
				if the button returned of the result = "No" then
					set the current view of window 1 to TheCurrentView
					return
				end if
			end if
			set theTotal to count of items of window 1
			set IconSize to icon size of icon view options of window 1
			set ArrangementValue to (arrangement of (icon view options of window 1))
		end if
		if ArrangementValue = not arranged then set ArrangementValue2 to "not arranged"
		if ArrangementValue = snap to grid then set ArrangementValue2 to "snap to grid"
		if ArrangementValue = arranged by name then set ArrangementValue2 to "arranged by name"
		if ArrangementValue = arranged by modification date then set ArrangementValue2 to "arranged by modification date"
		if ArrangementValue = arranged by creation date then set ArrangementValue2 to "arranged by creation date"
		if ArrangementValue = arranged by size then set ArrangementValue2 to "arranged by size"
		if ArrangementValue = arranged by kind then set ArrangementValue2 to "arranged by kind"
		if ArrangementValue = arranged by label then set ArrangementValue2 to "arranged by label"
		
		set AddendumText to ""
		if ListLength < theTotal then set AddendumText to "You have only selected " & ListLength & " of " & theTotal & " items. The new arrangement mightn't look good because the extra icons may end up all over the place." & return & return
		if ArrangementValue2 ≠ "not arranged" then
			display dialog "The window of the selection has a current arrangement of '" & ArrangementValue2 & "'. " & return & return & "Setting the window to 'not arranged' may have unexpected consequences for the icon arrangement." & return & return & AddendumText & "Do you want to proceed?" & return & return & "(You will be given a 'restore' option)." buttons {"Proceed", "No thanks"}
			if button returned of the result = "No thanks" then return
		end if
		if ArrangementValue2 ≠ "not arranged" then
			if we_are_on_desktop then
				set arrangement of icon view options of window of desktop to not arranged
			else
				try
					set (arrangement of icon view options of window 1) to not arranged
					close ptw
					open ptw
				on error errmsg
					display dialog errmsg
				end try
			end if
		end if
		my Qsort(Xdifflist, 1, (length of Xdifflist))
		my Qsort(ydiffList, 1, length of ydiffList)
		set LargestX to last item of Xdifflist
		set SmallestX to first item of Xdifflist
		set LargestY to last item of ydiffList
		set SmallestY to first item of ydiffList
		if not we_are_on_desktop then
			set WindowBounds to bounds of window 1
			set theYDim to (item 4 of WindowBounds) - (item 2 of WindowBounds)
			set theXDim to (item 3 of WindowBounds) - (item 1 of WindowBounds)
			set vertAdjust to 56
			if toolbar visible of window 1 = true then set vertAdjust to vertAdjust + 32
			if statusbar visible of window 1 = true then set vertAdjust to vertAdjust + 16
			
			if theYDim - vertAdjust < LargestY then
				display dialog "Currently the icons are vertically outside the dimensions of the window." & return & return & "Do you want to restrict them within the window top and bottom?" buttons {"Restrict 'em", "No", "Cancel"}
				if the button returned of the result = "Restrict 'em" then
					set LargestY to theYDim - vertAdjust
				end if
			end if
		end if
		--say (current date) - KeepDate as text
		
		if we_are_on_desktop then
			set seedValueadd to ((label position of icon view options of window of desktop) = right)
		else
			set seedValueadd to ((label position of icon view options of window 1) = right)
		end if
		
		-- If text is on right, double the minimum spacing
		if seedValueadd = true then
			set seedValue to seedValue * 2
			set staggered to false --<-- no need to stagger them
		end if
		-- Now the guessing part, what to ListLength as column spacing?
		if IconSize > seedValue then set seedValue to IconSize
		set setX to seedValue
		repeat with x from ((length of Xdifflist) - 1) to 1 by -1
			set diff to ((item (x + 1) of Xdifflist) - (item x of Xdifflist))
			if (diff > seedValue - 1) then set setX to diff
		end repeat
		--Now, set width between columns
		
		-- SPECIAL CASE : Roughly all on one horizontal line, then spread 'em evenly, else
		if LargestY - SmallestY < 60 and length of Xdifflist > 1 then
			set columnSpaces to (LargestX - SmallestX) div (((LargestX - SmallestX) div ((length of Xdifflist) - 1)))
		else
			set columnSpaces to ((LargestX - SmallestX + (setX / 2)) div setX)
		end if
		--Only 1 column? then set columnSpace to seedvalue
		if columnSpaces = 0 then
			set ColumnWidth to seedValue
			set columnSpaces to 1
		else
			if columnSpaces = 1 and (LargestX - SmallestX) < seedValue * 2 then
				set ColumnWidth to (LargestX - SmallestX)
			else
				set ColumnWidth to (LargestX - SmallestX) / columnSpaces
				if ColumnWidth < seedValue then set ColumnWidth to seedValue
				-- Roughly all on one horizontal line, then spread 'em evenly
				if LargestY - SmallestY < 60 then set ColumnWidth to (LargestX - SmallestX) / columnSpaces
			end if
		end if
		if staggered and columnSpaces > 0 then set staggered to ColumnWidth < (seedValue + 40)
		if staggered and columnSpaces > 1 then set LargestY to LargestY - 20
		set columnCount to columnSpaces + 1
		
		set columnCountStore to 0
		set columnXstore to {0, 0}
		repeat with x from 1 to columnSpaces
			set end of columnXstore to {0, 0}
			set columnCountStore to columnCountStore & 0
		end repeat
		repeat with x from 1 to columnCount
			set minX to SmallestX + ((x - 1) * ColumnWidth) - (ColumnWidth / 2)
			set MaxX to SmallestX + ((x - 1) * ColumnWidth) + (ColumnWidth / 2)
			set item x of columnXstore to {minX, MaxX}
		end repeat
		repeat with ThisItem in my KeepSelection
			if we_are_on_desktop then
				set temp to desktop position of ThisItem
			else
				set temp to position of ThisItem
			end if
			repeat with x from 1 to columnCount
				set minX to item 1 of item x of columnXstore
				set MaxX to item 2 of item x of columnXstore
				set tempX to item 1 of temp
				-- if icon falls in the range of column, add it up
				if ((tempX = minX) or (tempX > minX)) and (tempX < MaxX) then
					set item x of columnCountStore to ((item x of columnCountStore) + 1)
				end if
			end repeat
		end repeat
		--say (current date) - KeepDate as text
		if AlphaFlag then --> Alphabet arrange set
			set iconspacing to (LargestY - SmallestY) / ((ListLength / columnCount) div 1)
		else
			
			-- Now find Column with largest number of icons
			
			set maxCount to 2 ---> to avoid division by zero if only one row
			repeat with x from 1 to number of items in columnCountStore
				if item x of columnCountStore > maxCount then
					set maxCount to item x of columnCountStore
				end if
			end repeat
			set iconspacing to ((LargestY - SmallestY) / (maxCount - 1))
		end if
		--say (current date) - KeepDate as text
		if AlphaFlag then
			my SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
		else
			-- Now place Icons
			-- Loop ColumnCount times....
			repeat with MoveColumns from 1 to columnCount
				set minX to SmallestX + ((MoveColumns - 1) * ColumnWidth) - (ColumnWidth / 2)
				set MaxX to SmallestX + ((MoveColumns - 1) * ColumnWidth) + (ColumnWidth / 2)
				
				set templist to {}
				repeat with ThisItem from 1 to number of items in XYlist
					set temp to item ThisItem of XYlist
					set tempX to item 1 of temp
					if (((tempX = minX) or (tempX > minX)) and ((tempX < MaxX) or (tempX = MaxX))) then
						--Build list of icon XY positions in column
						set end of templist to tempX
						set end of templist to item 2 of temp
					end if
				end repeat
				-- This is the X value of the column
				set columnX to SmallestX + ((MoveColumns - 1) * ColumnWidth)
				--
				-- Now go and shift a column of the little bastards around!
				--
				my ArrangeColumn(templist, columnX, SmallestY, iconspacing, XYlist)
			end repeat
		end if
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			delay 0.2
			try
				activate
			end try
			select disk KeepDisk
			close window 1
		end if
		if not we_are_on_desktop then
			close ptw
			open ptw
			delay 1
		end if
	end tell
	--say (current date) - KeepDate as text
	set AddendumText to ""
	tell application "Finder"
		if we_are_on_desktop then
			repeat with SelectDisk in my KeepSelection
				tell application "System Events" to tell process "Finder"
					try
						select image (name of SelectDisk) of group 1 of scroll area 1
					end try
				end tell
			end repeat
		else
			try
				set t to container of (item 1 of ((items of window 1) as alias list)) as alias as text
				try
					set tt to (t & ".DS_Store") as text as alias
					set name of tt to "   temp1234567890"
					move ((t & "   temp1234567890") as text) to trash
				end try
				quit
				delay 0.2
				try
					activate
				end try
			on error errmsg
				display dialog errmsg
			end try
			repeat until exists process "Finder"
				delay 0.1
			end repeat
			
			select my KeepSelection
		end if
		--say (current date) - KeepDate as text
		display dialog "Restore?" & return & return & AddendumText & "Is this arrangement satisfactory?" buttons {"Yes", "No"}
		if button returned of the result = "No" then
			if we_are_on_desktop then
				repeat with x from 1 to ListLength
					set desktop position of item x of my KeepSelection to item x of IconPositions
				end repeat
				if FoundDisk then --< there is at least one disk in the mix, so restart Finder
					quit
					delay 0.2
					try
						activate
					end try
					select disk KeepDisk
					close window 1
				end if
				if ArrangementValue2 ≠ "not arranged" then set arrangement of icon view options of window of desktop to ArrangementValue
			else
				if ArrangementValue2 ≠ "not arranged" then
					set (arrangement of icon view options of window 1) to ArrangementValue
				else
					repeat with x from 1 to ListLength
						set position of item x of my KeepSelection to item x of IconPositions
					end repeat
				end if
			end if
			if not we_are_on_desktop then
				close ptw
				open ptw
			end if
		end if
		(*on error errmsg
			display dialog errmsg
		end try*)
		say "finished"
	end tell
end run

-- =============================================================

on ArrangeColumn(templist, currX, SmallestY, iconspacing, XYlist)
	tell application "Finder"
		try
			-- Start with a Y seed position, to overcome 
			-- problem with 1 entry not seen as an item
			set ylist to {0}
			--
			-- Now make list of Y positions
			repeat with Cycle from 1 to number of items in XYlist
				set temp to item Cycle of XYlist
				set ThisItem to item Cycle of my KeepSelection
				if temp is in templist then
					set ylist to ylist & item 2 of temp
				end if
			end repeat --
			-- Sort Y positions
			my Qsort(ylist, 1, length of ylist)
			--
			-- Now position each
			--display dialog number of items in XYlist as text
			repeat with Cycle from 1 to number of items in XYlist
				set thisItemTwo to item Cycle in my KeepSelection
				set temp to item Cycle of XYlist
				if we_are_on_desktop then
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set desktop position of thisItemTwo to {currX, currY + StaggeredCount}
					end if
				else
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set position of thisItemTwo to {currX, currY + StaggeredCount}
					end if
				end if
			end repeat
			if staggered then
				if StaggeredCount = 0 then
					set StaggeredCount to 20
				else
					set StaggeredCount to 0
				end if
			end if
		on error errmsg
			display dialog errmsg
		end try
	end tell
end ArrangeColumn

on SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
	
	tell application "Finder"
		try
			set templist to {}
			-- First, sort list of icons alphabetically
			set xx to length of my KeepSelection
			repeat with x from 1 to xx
				set end of templist to name of item x of my KeepSelection
			end repeat
			my Qsort(templist, 1, xx)
			set iconPos to 1
			set Xwidth to LargestX - SmallestX + ColumnWidth
			if staggered then set staggered to ColumnWidth < (seedValue + 40)
			repeat with ThisItem in my KeepSelection
				set tempName to name of ThisItem
				repeat with mainCount from 1 to xx
					if tempName = item mainCount of templist then
						set farRightX to ((mainCount - 1) * ColumnWidth)
						set numberofRows to ((farRightX) / (Xwidth)) div 1
						set Xposition to SmallestX + (farRightX - (numberofRows * Xwidth))
						set yposition to SmallestY + ((numberofRows) * iconspacing)
						set columntemp to (((Xposition - SmallestX) / ColumnWidth) + 0.5) div 1
						if staggered then
							set StaggeredCount to 0
							if (columntemp mod 2) = 1 then set StaggeredCount to 20
						end if
						
						if we_are_on_desktop then
							set desktop position of ThisItem to {Xposition, yposition + StaggeredCount}
						else
							set position of ThisItem to {Xposition, yposition + StaggeredCount}
						end if
						exit repeat
					end if
				end repeat
			end repeat
		end try
	end tell
end SortbyAlphabet

to Qsort(array, leftEnd, rightEnd) -- Hoare's QuickSort Algorithm
	script A
		property L : array
	end script
	set {i, j} to {leftEnd, rightEnd}
	set v to item ((leftEnd + rightEnd) div 2) of A's L -- pivot in the middle
	repeat while (j > i)
		repeat while (item i of A's L < v)
			set i to i + 1
		end repeat
		repeat while (item j of A's L > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell A's L to set {item i, item j} to {item j, item i} -- swap
			set {i, j} to {i + 1, j - 1}
		end if
	end repeat
	if (leftEnd < j) then Qsort(A's L, leftEnd, j)
	if (rightEnd > i) then Qsort(A's L, i, rightEnd)
end Qsort

Model: 27" iMac
Browser: Safari 533.19.4
Operating System: Mac OS X (10.6)

What a coercion grave!! :wink:

This does the same

set t to target of window 1 as text

The other as text coercions aren’t needed either.
The result class of a concatenation (&), if the operands could be concatenated, is always the class of the leftmost operand

Thanks Stefan, far more elegant.

While you’re there, do you happen to know how to make the renamed DS_Store visible?

It empties from the trash OK as an invisible object, but there’s nothing in the properties of the file to show the visible/invisible.

Regards

Santa

Removing the leading dot makes an item visible

G’day again Stefan

In this case it doesn’t. The renamed file is transferred to the trash, but the trash shows as still empty, and opening it up shows zilch.

However, commenting out the move to Trash line, and opening the resultant file with File Buddy info, shows the file as ticked invisible.

There must be a way that Apple flags invisible files without the dot in front.

Regards

Santa

If you want to delete the file anyway, why not


tell application "Finder" to set t to target of window 1 as text
try
	do shell script "/bim/rm " & quoted form of (POSIX path of t & ".DS_Store") & "; killall Finder"
end try


Stefan, thanks for that.

However my routine takes 3-5 seconds for a 214 icon window, as commented out below, and yours takes up to 17 seconds, with the shell script called as a routine (my part is embedded in a ‘tell Finder’ block).

Don’t know why the finder takes so long to recover in yours?


try
				set x to current date
				set t to target of window 1 as text
				my killFinder()

				(*try
					set tt to (t & ".DS_Store") as alias
					set name of tt to "   temp1234567890"
					move  (t & "   temp1234567890")  to trash
				end try
				quit
				delay 0.2*)

				try
					activate
				end try
				repeat until exists process "Finder"
					delay 0.1
				end repeat
			on error errmsg
				display dialog errmsg
			end try
			
			select my KeepSelection
			say (current date) - x as text
-- blah, blah, blah
on killFinder()
	try
		do shell script "/bim/rm " & quoted form of (POSIX path of t & ".DS_Store") & "; killall Finder"
	end try
end killFinder


You can also restart the Finder with Apple Events


tell application "Finder" to set t to target of window 1 as text
try
	do shell script "/bim/rm " & quoted form of (POSIX path of t & ".DS_Store")
end try
quit application "Finder"
delay 0.2
activate application "Finder"


The top script proved to be marginally the fastest with 20 runs, 165 seconds total, by 8 seconds per 20 loops (173 for the second). I was only renaming the DS_Store in the hope of making it visible.

Using the shell script killall Finder is definitely far slower though.

Many thanks as well, for pointing out the ‘target’ command.

Regards

Santa


tell application "Finder"
	set x to current date
	repeat 20 times
		try
			set keepselection to (select every item of window 1) as alias list
			set t to target of window 1 as text
			my killfinder()
			quit
			delay 0.2
			try
				activate
			end try
			repeat until exists process "Finder"
				delay 0.1
			end repeat
		on error errmsg
			display dialog errmsg
		end try
		
		select my keepselection
	end repeat
	say (current date) - x as text
	
end tell

on killfinder()
	try
		do shell script "/bim/rm " & quoted form of (POSIX path of t & ".DS_Store") --& "; killall Finder"
	end try
end killfinder


tell application "Finder"
	set x to current date
	repeat 20 times
		try
			set keepselection to (select every item of window 1) as alias list
			set t to target of window 1 as text
			try
				set tt to (t & ".DS_Store") as alias
				move (tt) to trash
			end try
			quit
			delay 0.2
			try
				activate
			end try
			repeat until exists process "Finder"
				delay 0.1
			end repeat
		on error errmsg
			display dialog errmsg
		end try
		
		select my keepselection
	end repeat
	say (current date) - x as text
	
end tell


Can’t be slower. Killall is execpt for kill the fastest way to quit an application. I tested it by 50 times rebooting the finder with clean code (no offence against you but your code got overall way too many overhead) and with quit command and killall. The killall command was almost 3 times faster than the quit command.

Also I don’t understand why you should restart the finder so many times. WHy not when you’re done with the window or when your script is completed a single restart.

Code to prove killall is way faster than quit

repeat 50 times
	quitFinder() --takes up to 32 seconds
	killallFinder() --takes up to 12 seconds; almost three times faster
end repeat

on quitFinder()
	tell application "Finder" to quit
	--repeat until finder is scriptable
	repeat
		try
			tell application "Finder" to count windows
			exit repeat
		end try
	end repeat
end quitFinder

on killallFinder()
	do shell script "killall Finder" --reboots immediatly
	--repeat until finder is scriptable
	repeat
		try
			tell application "Finder" to count windows
			exit repeat
		end try
	end repeat
end killallFinder

G’day DJ

Your routine worked out to be faster, but there seems to be a fundamental difference between the results of a ‘killall’ and a ‘Quit Finder’

Once the icons are arranged in the Finder windows, using a ‘Quit Finder’ locks them into position, but using a ‘killall’ resets them back to the original position.

As for the number of times I reset the Finder, bear in mind the following…

  1. Fact: when you move a desktop icon from position A to position B, the ‘desktop position’ property of the icon remains at position A, until you log out or reboot. So-- restart the Finder to lock in the desktop position.

  2. Bearing in mind fact 1, when reading the initial positions of the desktop, we don’t know if the user has moved them to a desired position. So-- the script restarts the Finder to lock in the desktop positions.

  3. Once we re-organize the icons with the script, the properties are still set at the old desktop positions. So-- restart the Finder to lock in the new desktop positions.

  4. When you move an icon in a window from A to B, the ‘position’ property stays the same as A until the window is closed and re-opened, and the Finder Quit.

Try running the script with the Quits commented out, you’ll soon see.

Edit: I’ve just realized, a ‘Quit’ means the Finder cleans up after itself; moved icons get reset. A ‘killall’ is a ‘Force Quit’, no garbage collection is carried out. That’s why a Quit Finder is slower, but necessary for my use.

Regards

Santa

I forgot about the saving part of the Finder that have to be done. You should like you said use the quit command instead then.

I agree with you about your statements except for your Edited part.

Garbage collection has nothing to de with terminating an application. Garbage collection is automated memory management at runtime so a coder doesn’t need to worry about that any-more or at least that’s the goal of a garbage collector. In theory an application with a garbage collector can run infinite without having memory leaks. The system will free all allocated memory of processes that don’t exists so freeing memory when the application is about to end is overkill so the Finder isn’t doing that as well.

(next paragraph is just a more detailed information why it will store or won’t)

In cocoa appkit there are some delegates of NSApplication when NSApplication receives the terminate method. The most important are applicationShouldTerminate and applicationWillTerminate. The first is used to ask the user if he’s sure he wants to quit for example and the second is used to store the data before the application is terminated. When using killall you’ll skip these delegate methods of your application. When using quit in applescript you’ll trigger the NSApp terminate call so those delegates, if they’re set, will also be handled. This is the actual reason why the Finder won’t store when using killall and using quit in applescript does store. Carbon applications are different but the concept remains the same.

G’day, and thanks DJ

To everyone…

Here’s the finished script.

Note that it’s intended for use as an adjunct to the Finders organizing, and originally was intended to line up icons on the right side of my desktop. It sort of grew from there.

Its original iteration was a script I wrote lodged with MacScripters some several years ago, called ‘Block of icons align and distribute’, a real mouthful.

It now offers to re-align icons to fit inside whatever window you have open, and works a bit different to the Finders re-sizing.

Please try it out, and post any changes you’d like. It’s basically been something to do to fill in time.

I’d be interested to know what’s the minimum system it will work on, but I suspect Snow Leopard is it.

Thanks for the help too!

Regards

Santa


--  ****************************
--  * Not Copyright, Brian Christmas     *
--  *                                                    *
--  *   From the Sunny Land of Oz        *
--  *             Version 2.0                      *
--  *             21 Jan 11                        *
--  *                                                    *
--  *        OzSanta@gmail.com             *
--  ****************************

-- AID or Automatic Icon Distributor

-- Minimum recommended System 10.6.6

-- Qsort routine from MacScripter
-- http://bbs.applescript.net/viewtopic.php?id=17340

-- Thanks to Yvan Koenig for the routine that traps
-- the Window of the Desktop that holds selected icons

-- This script works best if some approximate 
-- organizing is done first, otherwise extra columns
-- may be added, especially on horizontal single lines,
-- or columns left empty if you've left vertical gaps.

-- Feedback appreciated, especially suggestions to speed this up.

-- *******************************
-- **** Set this as minimum amount ****
-- ****   allowed between columns     ****
-- *******************************
property seedValue : 80
-- *******************************
-- **** Set this as minimum amount ****
-- ****          of icons to offer             ****
-- ****          alphabet sorting            ****
-- *******************************
property AlphabetMin : 20
-- *******************************
-- **** Set this to true to vertically    ****
-- **** stagger labels that are closer  ****
-- **** than seedvalue + 40 pixles    ****
-- *******************************
property staggered : false -- set to true or false
property StaggeredCount : 0
property we_are_on_desktop : false
property IconList : {}
property IconPositions : {}
property overlapFlag : false
property FoundDisk : true
property thelist : {}
property KeepSelection : {}
property templist : {}
property currX : 0
property SmallestY : 0
property iconspacing : 0
property XYlist : {}
property theWindow : {}
property ttt : 0
property HorizontalAdjustment : 1

on run
	tell application "Finder"
		set KeepDate to current date
		set currX to 0
		set LargestY to 0
		set SmallestY to 0
		set SmallestX to 0
		set LargestX to 0
		set overlapFlag to 0
		set Xdifflist to {}
		set ydiffList to {}
		set columnCount to {}
		set XYlist to {}
		set we_are_on_desktop to false
		--try
		
		try
			set tt to 0
			set ttt to 0
			set theWindow to window 1
			tell application "System Events" to tell process "Finder"
				set t to value of static text 1 of window 1
				if word 4 of t = "selected" then
					set tt to word 1 of t as number
					set ttt to word 3 of t as number
				end if
			end tell
		end try
		if tt > 500 then
			display dialog "There are " & tt & " items selected, out of " & ttt & ", and 'cause the Finder is slow with large numbers of icons in windows, I'm giving you the chance to Cancel." buttons {"Continue anyway", "Cancel"}
			if the button returned of the result = "Cancel" then return
		end if
		set my KeepSelection to the selection as alias list
		set ListLength to count of my KeepSelection
		if ListLength = 0 then
			display dialog "There are no icons selected." & return & return & "Try selecting some, and running the script again." buttons {"OK"}
			return
		end if
		if ListLength = 1 then
			display dialog "There is only one icon selected." & return & return & "Try selecting more, and running the script again." buttons {"OK"}
			return
		end if
		set FoundDisk to false
		set xx to ListLength
		repeat with x from 1 to ListLength
			if kind of item x of my KeepSelection as text ≠ "Volume" then
				set xx to x
				if FoundDisk then exit repeat
			else
				set FoundDisk to true
				set KeepDisk to item x of my KeepSelection
				if xx < ListLength then exit repeat
			end if
		end repeat
		set ThisItem to item xx of my KeepSelection
		set ptw to container of (ThisItem)
		if (count of windows) > 0 then
			try
				if name of window 1 = "Desktop" then
					tell application "Finder"
						activate
						set windName to get localized string "N5"
					end tell
					
					tell application "System Events" to tell application process "Finder" to tell menu bar 1 to tell menu bar item 7 to tell menu 1
						set noemi to (name of every menu item)
						if (noemi contains windName) then
							set windStatus to false
							repeat with i from 1 to count of noemi
								try (* to get rid of "missing value" *)
									if (name of menu item i is windName) and (value of attribute "AXMenuItemMarkChar" of menu item i is not "") then
										set windStatus to true
										exit repeat
									end if
								end try
							end repeat
							
						else
							set windStatus to false
						end if
					end tell
					if windStatus then
						tell application "Finder"
							try
								set EnclosingFolder to container of ThisItem as string
								close window "Desktop"
							end try
							display dialog "A Window belonging to the Desktop was frontmost, and you have selected Icons in it, and tried to organize them." & return & return & "Doing so may seriously disrupt your actual Desktop Icon arrangement." & return & return & "If you wish to organize any Desktop icons, please select them on the Desktop itself." buttons {"So, I've stopped it."}
							try
								open EnclosingFolder
							end try
						end tell
						return
					end if
				end if
			end try
		end if
		--- ARE WE ON THE DESKTOP?
		try
			set we_are_on_desktop to ((container of ThisItem as alias) is (path to desktop folder))
		on error
			set we_are_on_desktop to (kind of ThisItem as text = "Volume") --< only Volume icons selected
		end try
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			repeat
				try
					tell application "Finder" to count windows
					exit repeat
				end try
			end repeat
			select disk KeepDisk
			close window 1
		end if
		-- make array of positions
		if we_are_on_desktop then
			repeat with ThisItem from 1 to ListLength
				set temp to desktop position of item ThisItem of my KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		else
			repeat with ThisItem from 1 to ListLength
				set temp to position of item ThisItem of my KeepSelection
				set {end of XYlist, end of Xdifflist, end of ydiffList} to {temp, item 1 of temp, item 2 of temp}
			end repeat
		end if
		set IconPositions to XYlist
		set AlphaFlag to false
		-- Heaps of icons? then ask!
		if ListLength > (AlphabetMin - 1) then
			display dialog "There are " & ListLength & " icons selected." & return & return & "Do you want to sort them alphabetically or normally?" & return buttons {"Alphabetically please", "Normally thanks", "Cancel"}
			set AlphaFlag to (the button returned of the result is "Alphabetically please")
		end if
		if we_are_on_desktop then
			set theTotal to count of items of desktop
			set IconSize to icon size of icon view options of window of desktop
			set ArrangementValue to arrangement of icon view options of window of desktop
		else
			set TheCurrentView to current view of window 1
			if TheCurrentView ≠ icon view then
				set the current view of window 1 to icon view
				display dialog "I have reset the view of the window to 'icon view'. Do you wish to proceed?" buttons {"No", "Proceed"}
				if the button returned of the result = "No" then
					set the current view of window 1 to TheCurrentView
					return
				end if
			end if
			set theTotal to count of items of window 1
			set IconSize to icon size of icon view options of window 1
			set ArrangementValue to (arrangement of (icon view options of window 1))
		end if
		if ArrangementValue = not arranged then set ArrangementValue2 to "not arranged"
		if ArrangementValue = snap to grid then set ArrangementValue2 to "snap to grid"
		if ArrangementValue = arranged by name then set ArrangementValue2 to "arranged by name"
		if ArrangementValue = arranged by modification date then set ArrangementValue2 to "arranged by modification date"
		if ArrangementValue = arranged by creation date then set ArrangementValue2 to "arranged by creation date"
		if ArrangementValue = arranged by size then set ArrangementValue2 to "arranged by size"
		if ArrangementValue = arranged by kind then set ArrangementValue2 to "arranged by kind"
		if ArrangementValue = arranged by label then set ArrangementValue2 to "arranged by label"
		
		set AddendumText to ""
		if ListLength < theTotal then set AddendumText to "You have only selected " & ListLength & " of " & theTotal & " items. The new arrangement mightn't look good because the extra icons could be anywhere in the window." & return & return
		if ArrangementValue2 ≠ "not arranged" then
			display dialog "The windows current arrangement is '" & ArrangementValue2 & "'. " & return & return & "Setting the window to 'not arranged' may have unexpected consequences for the icon arrangement." & return & return & AddendumText & "Do you want to proceed?" & return & return & "(You will be given a 'restore' option)." buttons {"Proceed", "No thanks"}
			if button returned of the result = "No thanks" then return
		end if
		if ArrangementValue2 ≠ "not arranged" then
			if we_are_on_desktop then
				set arrangement of icon view options of window of desktop to not arranged
			else
				try
					set (arrangement of icon view options of window 1) to not arranged
					close ptw
					open ptw
				on error errmsg
					display dialog errmsg
				end try
			end if
		end if
		my Qsort(Xdifflist, 1, (length of Xdifflist))
		my Qsort(ydiffList, 1, length of ydiffList)
		set LargestX to last item of Xdifflist
		set SmallestX to first item of Xdifflist
		set LargestY to last item of ydiffList
		set SmallestY to first item of ydiffList
		if not we_are_on_desktop then
			set WindowBounds to bounds of window 1
			set theYDim to (item 4 of WindowBounds) - (item 2 of WindowBounds)
			set theXDim to (item 3 of WindowBounds) - (item 1 of WindowBounds)
			set vertAdjust to 64
			set HorizontalAdjustment to 1
			if toolbar visible of window 1 = true then set vertAdjust to vertAdjust + 40
			if statusbar visible of window 1 = true then set vertAdjust to vertAdjust + 24
			set SideWidth to (sidebar width of window 1)
			if theYDim - vertAdjust < LargestY then
				display dialog "Some of the icons are below the window." & return & return & "Do you want to move the icons to within the window frame?" buttons {"Move them", "No", "Cancel"}
				if the button returned of the result = "Move them" then
					set LargestY to theYDim - vertAdjust
				end if
			else
				if theYDim - vertAdjust > LargestY then
					display dialog "The Window is taller than the icons." & return & return & "Do you want to expand the icons between the window top and bottom?" buttons {"Expand them", "No", "Cancel"}
					if the button returned of the result = "Expand them" then
						set LargestY to theYDim - vertAdjust
					end if
				end if
			end if
			set HorizontalAdjustment to 1
			if LargestX + 70 > theXDim - SideWidth then
				display dialog "Some of the icons are to the side of the window." & return & return & "Do you want to move the side icons to within the window frame?" buttons {"Move them", "No", "Cancel"}
				if the button returned of the result = "Move them" then
					set HorizontalAdjustment to (theXDim - SideWidth) / ((LargestX - SmallestX) + (IconSize + SideWidth + 40))
				end if
			else
				if LargestX + SideWidth + IconSize + 40 < theXDim - SideWidth then --40
					display dialog "The Window is wider than the icons." & return & return & "Do you want to expand the icons between the window sides?" buttons {"Expand them", "No", "Cancel"}
					if the button returned of the result = "Expand them" then
						set HorizontalAdjustment to (theXDim - SideWidth) / ((LargestX - SmallestX) + (IconSize + SideWidth + 40))
					end if
				end if
			end if
		end if
		if we_are_on_desktop then
			set seedValueadd to ((label position of icon view options of window of desktop) = right)
		else
			set seedValueadd to ((label position of icon view options of window 1) = right)
		end if
		-- If text is on right, double the minimum spacing
		if seedValueadd = true then
			set seedValue to seedValue * 2
			set staggered to false --<-- no need to stagger them
		end if
		-- Now the guessing part, what to ListLength as column spacing?
		if IconSize > seedValue then set seedValue to IconSize
		set setX to seedValue
		repeat with x from ((length of Xdifflist) - 1) to 1 by -1
			set diff to ((item (x + 1) of Xdifflist) - (item x of Xdifflist))
			if (diff > seedValue - 1) then set setX to diff
		end repeat
		--Now, set width between columns
		-- SPECIAL CASE : Roughly all on one horizontal line, then spread 'em evenly, else
		if LargestY - SmallestY < 60 and length of Xdifflist > 1 then
			set columnSpaces to (LargestX - SmallestX) div (((LargestX - SmallestX) div ((length of Xdifflist) - 1)))
		else
			set columnSpaces to ((LargestX - SmallestX + (setX / 2)) div setX)
		end if
		--Only 1 column? then set columnSpace to seedvalue
		if columnSpaces = 0 then
			set ColumnWidth to seedValue
			set columnSpaces to 1
		else
			if columnSpaces = 1 and (LargestX - SmallestX) < seedValue * 2 then
				set ColumnWidth to (LargestX - SmallestX)
			else
				set ColumnWidth to (LargestX - SmallestX) / columnSpaces
				if ColumnWidth < seedValue then set ColumnWidth to seedValue
				-- Roughly all on one horizontal line, then spread 'em evenly
				if LargestY - SmallestY < 60 then set ColumnWidth to (LargestX - SmallestX) / columnSpaces
			end if
		end if
		if staggered and columnSpaces > 0 then set staggered to ColumnWidth < (seedValue + 40)
		if staggered and columnSpaces > 1 then set LargestY to LargestY - 20
		set columnCount to columnSpaces + 1
		
		set columnCountStore to 0
		set columnXstore to {0, 0}
		repeat with x from 1 to columnSpaces
			set end of columnXstore to {0, 0}
			set columnCountStore to columnCountStore & 0
		end repeat
		repeat with x from 1 to columnCount
			set minX to SmallestX + ((x - 1) * ColumnWidth) - (ColumnWidth / 2)
			set MaxX to SmallestX + ((x - 1) * ColumnWidth) + (ColumnWidth / 2)
			set item x of columnXstore to {minX, MaxX}
		end repeat
		repeat with ThisItem in my KeepSelection
			if we_are_on_desktop then
				set temp to desktop position of ThisItem
			else
				set temp to position of ThisItem
			end if
			repeat with x from 1 to columnCount
				set minX to item 1 of item x of columnXstore
				set MaxX to item 2 of item x of columnXstore
				set tempX to item 1 of temp
				-- if icon falls in the range of column, add it up
				if ((tempX = minX) or (tempX > minX)) and (tempX < MaxX) then
					set item x of columnCountStore to ((item x of columnCountStore) + 1)
				end if
			end repeat
		end repeat
		if AlphaFlag then --> Alphabet arrange set
			set iconspacing to (LargestY - SmallestY) / ((ListLength / columnCount) div 1)
		else
			
			-- Now find Column with largest number of icons
			
			set maxCount to 2 ---> to avoid division by zero if only one row
			repeat with x from 1 to number of items in columnCountStore
				if item x of columnCountStore > maxCount then
					set maxCount to item x of columnCountStore
				end if
			end repeat
			set iconspacing to ((LargestY - SmallestY) / (maxCount - 1))
		end if
		--say (current date) - KeepDate as text
		if AlphaFlag then
			my SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
		else
			-- Now place Icons
			-- Loop ColumnCount times....
			repeat with MoveColumns from 1 to columnCount
				set minX to SmallestX + ((MoveColumns - 1) * ColumnWidth) - (ColumnWidth / 2)
				set MaxX to SmallestX + ((MoveColumns - 1) * ColumnWidth) + (ColumnWidth / 2)
				
				set templist to {}
				repeat with ThisItem from 1 to number of items in XYlist
					set temp to item ThisItem of XYlist
					set tempX to item 1 of temp
					if (((tempX = minX) or (tempX > minX)) and ((tempX < MaxX) or (tempX = MaxX))) then
						--Build list of icon XY positions in column
						set end of templist to tempX
						set end of templist to item 2 of temp
					end if
				end repeat
				-- This is the X value of the column
				set columnX to SmallestX + ((MoveColumns - 1) * ColumnWidth)
				--
				-- Now go and shift a column of the little bastards around!
				--
				my ArrangeColumn(templist, columnX, SmallestY, iconspacing, XYlist)
			end repeat
		end if
		if FoundDisk then --< there is at least one disk in the mix, so restart Finder
			quit
			repeat
				try
					tell application "Finder" to count windows
					exit repeat
				end try
			end repeat
			select disk KeepDisk
			close window 1
		end if
		if not we_are_on_desktop then
			close ptw
			open ptw
			delay 1
		end if
		if we_are_on_desktop then
			repeat with SelectDisk in my KeepSelection
				tell application "System Events" to tell process "Finder"
					try
						select image (name of SelectDisk) of group 1 of scroll area 1
					end try
				end tell
			end repeat
		else
			try
				set t to target of window 1 as text
				my killFinderStore()
				quit
				repeat
					try
						tell application "Finder" to count windows
						exit repeat
					end try
				end repeat
			on error errmsg
				display dialog errmsg
			end try
			try
				delay 1
				select my KeepSelection
			end try
		end if
		display dialog "Restore option" & return & return & AddendumText & "Is this arrangement satisfactory?" buttons {"Yes", "No"}
		if button returned of the result = "No" then
			if we_are_on_desktop then
				repeat with x from 1 to ListLength
					set desktop position of item x of my KeepSelection to item x of IconPositions
				end repeat
				if FoundDisk then --< there is at least one disk in the mix, so restart Finder
					quit
					repeat
						try
							tell application "Finder" to count windows
							exit repeat
						end try
					end repeat
					select disk KeepDisk
					close window 1
				end if
				if ArrangementValue2 ≠ "not arranged" then set arrangement of icon view options of window of desktop to ArrangementValue
			else
				if ArrangementValue2 ≠ "not arranged" then
					set (arrangement of icon view options of window 1) to ArrangementValue
				else
					repeat with x from 1 to ListLength
						set position of item x of my KeepSelection to item x of IconPositions
					end repeat
				end if
			end if
			if not we_are_on_desktop then
				close ptw
				open ptw
			end if
		end if
		say "finished"
	end tell
end run

-- =============================================================

on killFinderStore()
	try
		do shell script "/bim/rm " & quoted form of (POSIX path of t & ".DS_Store")
	end try
end killFinderStore

on ArrangeColumn(templist, currX, SmallestY, iconspacing, XYlist)
	tell application "Finder"
		try
			-- Start with a Y seed position, to overcome 
			-- problem with 1 entry not seen as an item
			set ylist to {0}
			--
			-- Now make list of Y positions
			repeat with Cycle from 1 to number of items in XYlist
				set temp to item Cycle of XYlist
				set ThisItem to item Cycle of my KeepSelection
				if temp is in templist then
					set ylist to ylist & item 2 of temp
				end if
			end repeat --
			-- Sort Y positions
			my Qsort(ylist, 1, length of ylist)
			--
			-- Now position each
			--display dialog number of items in XYlist as text
			repeat with Cycle from 1 to number of items in XYlist
				set thisItemTwo to item Cycle in my KeepSelection
				set temp to item Cycle of XYlist
				if we_are_on_desktop then
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set desktop position of thisItemTwo to {currX, currY + StaggeredCount}
					end if
				else
					if temp is in templist then
						set tempY to item 2 of temp
						repeat with countdown from 2 to (number of items in ylist)
							if item countdown of ylist = tempY then
								set currY to SmallestY + ((countdown - 2) * iconspacing)
								set item countdown of ylist to "Done"
								exit repeat
							end if
						end repeat
						set position of thisItemTwo to {currX * HorizontalAdjustment, currY + StaggeredCount}
					end if
				end if
			end repeat
			if staggered then
				if StaggeredCount = 0 then
					set StaggeredCount to 20
				else
					set StaggeredCount to 0
				end if
			end if
		on error errmsg
			display dialog errmsg
		end try
	end tell
end ArrangeColumn

on SortbyAlphabet(SmallestX, LargestX, SmallestY, ColumnWidth, iconspacing)
	tell application "Finder"
		try
			set templist to {}
			-- First, sort list of icons alphabetically
			set xx to length of my KeepSelection
			repeat with x from 1 to xx
				set end of templist to name of item x of my KeepSelection
			end repeat
			my Qsort(templist, 1, xx)
			set iconPos to 1
			set Xwidth to LargestX - SmallestX + ColumnWidth
			if staggered then set staggered to ColumnWidth < (seedValue + 40)
			repeat with ThisItem in my KeepSelection
				set tempName to name of ThisItem
				repeat with mainCount from 1 to xx
					if tempName = item mainCount of templist then
						set farRightX to ((mainCount - 1) * ColumnWidth)
						set numberofRows to ((farRightX) / (Xwidth)) div 1
						set Xposition to SmallestX + (farRightX - (numberofRows * Xwidth))
						set yposition to SmallestY + ((numberofRows) * iconspacing)
						set columntemp to (((Xposition - SmallestX) / ColumnWidth) + 0.5) div 1
						if staggered then
							set StaggeredCount to 0
							if (columntemp mod 2) = 1 then set StaggeredCount to 20
						end if
						
						if we_are_on_desktop then
							set desktop position of ThisItem to {Xposition, yposition + StaggeredCount}
						else
							set position of ThisItem to {Xposition * HorizontalAdjustment, yposition + StaggeredCount}
						end if
						exit repeat
					end if
				end repeat
			end repeat
		end try
	end tell
end SortbyAlphabet

to Qsort(array, leftEnd, rightEnd) -- Hoare's QuickSort Algorithm
	script A
		property L : array
	end script
	set {i, j} to {leftEnd, rightEnd}
	set v to item ((leftEnd + rightEnd) div 2) of A's L -- pivot in the middle
	repeat while (j > i)
		repeat while (item i of A's L < v)
			set i to i + 1
		end repeat
		repeat while (item j of A's L > v)
			set j to j - 1
		end repeat
		if (not i > j) then
			tell A's L to set {item i, item j} to {item j, item i} -- swap
			set {i, j} to {i + 1, j - 1}
		end if
	end repeat
	if (leftEnd < j) then Qsort(A's L, leftEnd, j)
	if (rightEnd > i) then Qsort(A's L, i, rightEnd)
end Qsort