G’day
I’m trying to update a script for organizing icons on the desktop and in windows, to make it compatible with Snow Leopard.
Everything works OK except for re-selecting the original selection after they’ve been moved on the desktop. I can’t work out how to select any chosen Disk icons along with the ordinary icons.
The variable keepSelection stores the original selection, including disk icons, but only restores non-disk icons
if we_are_on_desktop then set the selection to KeepSelection --< is the part I need to change
Any advice appreciated.
Regards
Santa
-- ****************************
-- * Copyright 2011, 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.
global IconList
global IconPositions
global overlapFlag
global we_are_on_desktop
global seedValue
global AlphabetMin
global staggered
global StaggeredCount
global FoundDisk
global thelist
global KeepSelection
set StaggeredCount to 0
-- *******************************
-- **** 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
-- *******************************
-- **** Set this to true to vertically ****
-- **** stagger labels that are closer ****
-- **** than seedvalue + 40 pixles ****
-- *******************************
set staggered to false -- set to true or false
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 overlapFlag to 0
set Xdifflist to {}
set ydiffList to {}
set columnCount to {}
set XYlist to {}
try
set thelist to (selection as list)
set KeepSelection to the selection
set distribute to count of thelist
if distribute = 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 distribute = 1 then return -- Only one selected, so leave alone
set FoundDisk to false
set xx to distribute
repeat with x from 1 to distribute
if kind of item x of thelist as text ≠"Volume" then
set xx to x
if FoundDisk then exit repeat
else
set FoundDisk to true
set KeepDisk to item x of thelist as alias
if xx < distribute then exit repeat
end if
end repeat
set ThisItem to item xx of thelist
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.4
try
activate
end try
select disk KeepDisk
close window 1
end if
-- make array of positions
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 end of XYlist to temp
set end of Xdifflist to item 1 of temp
set end of ydiffList to item 2 of temp
end repeat
set IconList to thelist
--display dialog item 1 of XYlist as text
set IconPositions to XYlist
set AlphaFlag to false
-- Heaps of icons? then ask!
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
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
set AddendumText to ""
if (count of thelist) < theTotal then set AddendumText to "You have only selected " & (count of thelist) & " of " & theTotal & " items. The new arrangement mightn't look good because the extra icons may end up all over the place." & return & return & "You will however, be given a 'restore' option." & return & return
if ArrangementValue as text ≠"not arranged" then
display dialog "The window of the selection has a current arrangement of '" & ArrangementValue & "'. " & return & return & AddendumText & "Do you want to proceed?" buttons {"Proceed", "No thanks"}
if button returned of the result = "No thanks" then return
end if
if ArrangementValue as text ≠"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
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 distribute 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 if
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 thelist
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) / ((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 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(thelist, templist, columnX, SmallestY, iconspacing, XYlist)
end repeat
end if
if not we_are_on_desktop then
close ptw
open ptw
end if
if not we_are_on_desktop then select every item of IconList
if we_are_on_desktop then set the selection to KeepSelection --< Need to alter this
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 count of IconList
set desktop position of item x of IconList to item x of IconPositions
end repeat
if ArrangementValue as text ≠"not arranged" then set arrangement of icon view options of window of desktop to ArrangementValue
else
if ArrangementValue as text ≠"not arranged" then
set (arrangement of icon view options of window 1) to ArrangementValue
else
repeat with x from 1 to count of IconList
set position of item x of IconList 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
end try
end tell
end mainCycle
-- =============================================================
on ArrangeColumn(thelist, 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 thelist
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
repeat with Cycle from 1 to number of items in XYlist
set thisItemTwo to item Cycle in thelist
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
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 end of templist to name of item x of thelist
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 thelist
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)