G’day Adam
I definately think there’s a bug in the Hoaer’s Qsort Routine.
I’ve re-submitted my latest version of the icon arranger, but using a modified version of it I’ve been able to asertain there’s an error that’s reproducable.
I’ll post the modified version here, and hope it’s not too long.
Use it to arrange a window with lots of icons, alphabetically. It won’t beep on the first pass.
Now arrange alphabetically again, while the icons are still selected. You’ll get at least one beep (or at least, I can).
Rinse & Repeat
Fingers crossed it works for you as it does for me.
(Edit) I’ve just found it won’t beep if it’s run on a folder that’s been organized by name by the Finder. The icons have to be physically shifted by the routine, before it will beep. Play around with it, scrunch 'em up tight, then arrange 'em Alphabetically.
Regards, Santa
-- ****************************
-- * Copyright 2006, Brian Christmas *
-- * *
-- * From the Sunny Land of Oz *
-- * Version 1.2 *
-- * 31/07/06 *
-- * *
-- * bec9@tpg.com.au *
-- ****************************
-- Qsort routine from MacScripter
-- http://bbs.applescript.net/viewtopic.php?id=17340
-- This script works best if some approximate
-- organizing is done first, otherwise
-- extra columns may be added.
-- Also note that if insufficient side margins are not allowed for when arranging a window,
-- the Finder may 'shake' the window from side to side, thereby altering the icon placement.
-- In addition, if you have a window open showing the desktop icons in it, DON'T try to
-- arrange the window. It only organizes the ACTUAL desktop. Hairy things happen to it.
-- Feedback appreciated, especially suggestions to speed this up.
global overlapFlag
global we_are_on_desktop
global seedValue
global AlphabetMin
-- *******************************
-- **** Set this as minimum amount ****
-- **** allowed between columns ****
-- *******************************
set seedValue to 100
-- *******************************
-- **** Set this as minimum amount ****
-- **** of icons to offer ****
--**** alphabet sorting ****
-- *******************************
set AlphabetMin to 20
my mainCycle()
on mainCycle()
tell application "Finder"
set currX to 0
set LargestY to 0
set SmallestY to 0
set SmallestX to 0
set LargestX to 0
set listofXY to ""
set overlapFlag to 0
set Xdifflist to ""
set ydiffList to ""
set columnCount to ""
try
-- make array of positions
set thelist to (selection as list)
set distribute to number of items in thelist
--- ARE WE ON THE DESKTOP?
if distribute = 0 then
display dialog "There are no icons selected." & return & return & "Try selecting some, and running the script again." buttons {"OK"}
end if
set thisItem to item 1 of thelist
set we_are_on_desktop to ((folder of thisItem as alias) is (path to desktop folder))
-- Heaps of icons? then ask!
set AlphaFlag to false
if length of thelist > (AlphabetMin - 1) then
display dialog " there are " & length of thelist & " 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
repeat with thisItem in thelist
if we_are_on_desktop then
set temp to desktop position of thisItem
else
set temp to position of thisItem
end if
set listofXY to listofXY & item 1 of temp & item 2 of temp as list
--set listofXY to listofXY & item 2 of temp as list
set Xdifflist to Xdifflist & item 1 of temp as list
set ydiffList to ydiffList & item 2 of temp as list
end repeat
my Qsort(Xdifflist, 1, (length of Xdifflist))
my Qsort(ydiffList, 1, length of ydiffList)
-- these are necessary 'cause Hoare's sort routine is faulty!!!
set LargestX to last item of Xdifflist
set SmallestX to 10000
set LargestY to 0
set SmallestY to 10000
repeat with x from 1 to length of Xdifflist
if LargestX < item x of Xdifflist then
beep
set LargestX to item x of Xdifflist
end if
if SmallestX > item x of Xdifflist then set SmallestX to item x of Xdifflist
if LargestY < item x of ydiffList then set LargestY to item x of ydiffList
if SmallestY > item x of ydiffList then set SmallestY to item x of ydiffList
end repeat
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
-- Now the guessing part, what to distribute as column spacing?
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 < (2 + ((LargestX - SmallestX) / 2)) then
if (diff > seedValue - 1) then
set setX to diff
end if
end if
end repeat
--Now, set width between columns
set columnSpaces to ((LargestX - SmallestX + (setX / 2)) div setX)
--Only 1 column? then set columnSpace to ....
if columnSpaces < 2 then set columnSpaces to columnSpaces + 1
set ColumnWidth to (LargestX - SmallestX) / columnSpaces
if ColumnWidth < seedValue then set ColumnWidth to seedValue
set columnCount to columnSpaces + 1
set columnCountStore to 0
repeat with x from 1 to columnSpaces
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)
repeat with thisItem in thelist
if we_are_on_desktop then
set temp to desktop position of thisItem
else
set temp to position of thisItem
end if
set tempY to item 2 of temp
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) / ((distribute / 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
if AlphaFlag then
my SortbyAlphabet(thelist, SmallestX, LargestX, SmallestY, ColumnWidth, IconSpacing)
else
-- Now place Icons
-- Loop ColumnCount times....
repeat with MoveColumns from 1 to columnCount
set tempList to ""
set minX to SmallestX + ((MoveColumns - 1) * ColumnWidth) - (ColumnWidth / 2)
set maxX to SmallestX + ((MoveColumns - 1) * ColumnWidth) + (ColumnWidth / 2)
repeat with thisItem in thelist
if we_are_on_desktop then
set temp to desktop position of thisItem
else
set temp to position of thisItem
end if
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
if tempList = "" then
set tempList to tempX as list
set tempList to tempList & item 2 of temp
else
set tempList to tempList & tempX
set tempList to tempList & item 2 of temp
end if
end if
end repeat
-- This is the X value of the column
set tempX to SmallestX + ((MoveColumns - 1) * ColumnWidth)
--
-- Now go and shift a column of the little bastards around!
--
my ArrangeColumn(thelist, tempList, tempX, SmallestY, IconSpacing)
end repeat
end if
end try
if overlapFlag > 0 then
if overlapFlag = 1 then
set Errormessage to "There was an overlapping icon." & return & return & "I'll try running the script again, as I've nudged it."
else
set Errormessage to "There were " & overlapFlag & " overlapping icons." & return & return & "I'll try running the script again, as I've nudged them."
end if
display dialog Errormessage buttons {"OK", "Cancel"}
if (the button returned of the result is "OK") then
my mainCycle() -- Do the run around again
end if
end if
end tell
end mainCycle
-- =============================================================
on ArrangeColumn(thelist, tempList, currX, SmallestY, IconSpacing)
tell application "Finder"
set listofXY to ""
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 thisItem in thelist
repeat
if we_are_on_desktop then
set temp to desktop position of thisItem
else
set temp to position of thisItem
end if
if temp is in tempList then
if item 2 of temp is in Ylist then --> Oops! Some icons together!
set tempShift to item 1 of temp & ((item 2 of temp) + 1 + overlapFlag)
set overlapFlag to overlapFlag + 1
--Nudge overlapping icons
if we_are_on_desktop then
set desktop position of thisItem to tempShift
else
set position of thisItem to tempShift
end if
-- now reset templist Y position
set x to 2
repeat
if item x of tempList = item 2 of temp then
set item x of tempList to item 2 of tempShift
exit repeat
else
set x to (x + 2)
if x > number of items in tempList then exit repeat --> just in case
end if
end repeat
else
set Ylist to Ylist & item 2 of temp
exit repeat
end if
else
exit repeat
end if
end repeat
end repeat
--
-- Sort Y positions
my Qsort(Ylist, 1, length of Ylist)
--
-- Now position each
repeat with thisItemTwo in thelist
if we_are_on_desktop then
set temp to desktop position of thisItemTwo
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 countdown to (number of items in Ylist)
end if
end repeat
set desktop position of thisItemTwo to {currX, currY}
end if
else
set temp to position of thisItemTwo
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 countdown to number of items in Ylist
end if
end repeat
set position of thisItemTwo to {currX, currY}
end if
end if
end repeat
end try
end tell
end ArrangeColumn
on SortbyAlphabet(thelist, SmallestX, LargestX, SmallestY, ColumnWidth, IconSpacing)
tell application "Finder"
try
set tempList to ""
-- First, sort list of icons alphabetically
set xx to length of thelist
repeat with x from 1 to xx
set firstGo to name of item x of thelist as string
if tempList = "" then
set tempList to firstGo as list
else
set tempList to tempList & firstGo as list
end if
end repeat
my Qsort(tempList, 1, xx)
set iconPos to 1
repeat with mainCount from 1 to xx
set Xposition to SmallestX + ((iconPos - 1) * ColumnWidth)
set tempName to item mainCount of tempList
repeat with thisItem in thelist
if tempName = name of thisItem then
if we_are_on_desktop then
set desktop position of thisItem to {Xposition, SmallestY}
else
set position of thisItem to {Xposition, SmallestY}
end if
set iconPos to iconPos + 1
if iconPos > (((LargestX - SmallestX) / ColumnWidth) + 1) then
set iconPos to 1
set SmallestY to SmallestY + IconSpacing
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
(Edit) This was the bit that was modified
set LargestX to last item of Xdifflist
set SmallestX to 10000
set LargestY to 0
set SmallestY to 10000
repeat with x from 1 to length of Xdifflist
if LargestX < item x of Xdifflist then
beep
set LargestX to item x of Xdifflist
end if
if SmallestX > item x of Xdifflist then set SmallestX to item x of Xdifflist
if LargestY < item x of ydiffList then set LargestY to item x of ydiffList
if SmallestY > item x of ydiffList then set SmallestY to item x of ydiffList
end repeat
Model: G5
AppleScript: 1.10.7
Browser: Safari 419.3
Operating System: Mac OS X (10.4)