続グリッド
これの続き。一応違和感のないくらいには賢くなったはず。
Option キーをこんなに使うのも久しぶりというくらい使いまくり。
ちょっと長過ぎて小汚いコードになってしまった…。
追記: さっき Leopard の Terminal.app で使ってみたら、そもそも Terminal.app が高機能になっていて不要なのと仕様が違うのとで全然使い物になりませんでした。。。
on createOverlappingPair(_first, _second, _xRange) script OverlappingPair property FirstWindowIndex : _first property SecondWindowIndex : _second property xRange : _xRange to theOtherOneOf(theItem) if theItem = SecondWindowIndex then return FirstWindowIndex else return SecondWindowIndex end if end theOtherOneOf end script return OverlappingPair end createOverlappingPair on calculateOverlappingXRange(theBounds, theBoundsOfAnother) if the item 1 of theBounds > the item 3 of theBoundsOfAnother then return (the item 3 of theBoundsOfAnother) - (the item 1 of theBounds) else if the item 3 of theBounds < the item 1 of theBoundsOfAnother then return (the item 3 of theBounds) - (the item 1 of theBoundsOfAnother) else if the item 1 of theBounds < the item 3 of theBoundsOfAnother and ¬ the item 3 of theBounds ≥ the item 3 of theBoundsOfAnother then return (the item 3 of theBoundsOfAnother) - (the item 1 of theBounds) else if the item 3 of theBounds > the item 1 of theBoundsOfAnother and ¬ the item 3 of theBoundsOfAnother ≥ the item 3 of theBounds then return (the item 3 of theBounds) - (the item 1 of theBoundsOfAnother) end if return 0 end calculateOverlappingXRange on calculateOverlappingYRange(theBounds, theBoundsOfAnother) if the item 2 of theBounds > the item 4 of theBoundsOfAnother then return (the item 4 of theBoundsOfAnother) - (the item 2 of theBounds) else if the item 4 of theBounds < the item 2 of theBoundsOfAnother then return (the item 4 of theBounds) - (the item 2 of theBoundsOfAnother) else if the item 2 of theBounds < the item 4 of theBoundsOfAnother and ¬ the item 4 of theBounds ≥ the item 4 of theBoundsOfAnother then return (the item 4 of theBoundsOfAnother) - (the item 2 of theBounds) else if the item 4 of theBounds > the item 2 of theBoundsOfAnother and ¬ the item 4 of theBoundsOfAnother ≥ the item 4 of theBounds then return (the item 4 of theBounds) - (the item 2 of theBoundsOfAnother) end if return 0 end calculateOverlappingYRange on abs(theValue) if theValue < 0 then return -theValue else return theValue end if end abs tell application "Finder" to set theWorkspaceBounds to the bounds of the window of the desktop tell application "Terminal" set theWindows to {} set theBoundsList to {} set theWindowIndicesSortedByPos to {} set theNumberOfWindows to (the count of the window) - 1 if theNumberOfWindows ≤ 1 then return repeat with theWindow in the windows if the index of theWindow > theNumberOfWindows ¬ then exit repeat set theWindows to theWindows & {theWindow} set theBounds to the bounds of theWindow set theBoundsList to theBoundsList & {theBounds} set theWindowIndicesSortedByPos to theWindowIndicesSortedByPos & {0} end repeat set theOverlappingPairs to {} set theNearestNeighborXRangeList to {} set theWindowGroups to {} set theWindowGroupIndices to {} set theOverlappingXRange to 0 repeat with theIndex from 1 to (the count of theBoundsList) set theMinimumIndex to 0 set theMaximumOverlappingXRange to 0 set theBounds to the item (theIndex) of theBoundsList set theMinimumXInThisIteration to 999999 repeat with theAnotherIndex from 1 to the count of theBoundsList set theBoundsOfAnother to the item (theAnotherIndex) of theBoundsList if theIndex is not theAnotherIndex then set theOverlappingXRange to ¬ me's calculateOverlappingXRange(theBounds, theBoundsOfAnother) if theMaximumOverlappingXRange = 0 or ¬ theOverlappingXRange > theMaximumOverlappingXRange then set theMaximumOverlappingXRange to theOverlappingXRange end if set theOverlappingPairs to theOverlappingPairs & {¬ me's createOverlappingPair(theIndex, theAnotherIndex, theOverlappingXRange)} end if if theAnotherIndex is not in theWindowIndicesSortedByPos and ¬ theMinimumXInThisIteration ≥ the item 1 of theBoundsOfAnother then set theMinimumIndex to theAnotherIndex set theMinimumXInThisIteration to the item 1 of theBoundsOfAnother end if end repeat set theWindowGroups to theWindowGroups & {{}} set theWindowGroupIndices to theWindowGroupIndices & {0} repeat until (the count of theNearestNeighborXRangeList) ≥ theIndex set theNearestNeighborXRangeList to theNearestNeighborXRangeList & {null} end repeat set the item (theIndex) of theNearestNeighborXRangeList to theMaximumOverlappingXRange set the item (theIndex) of theWindowIndicesSortedByPos to theMinimumIndex end repeat set theRealNumberOfWindowGroups to 0 set theAverageWidthOfTheWindow to 0 repeat with theIndex from 1 to the count of theBoundsList set unpaired to true set theBounds to the item (theIndex) of theBoundsList set theNearestNeighborXRange to the item (theIndex) of theNearestNeighborXRangeList set theWidthOfTheWindow to the (item 3 of theBounds) - the (item 1 of theBounds) set theAverageWidthOfTheWindow to theAverageWidthOfTheWindow + theWidthOfTheWindow if theNearestNeighborXRange > theWidthOfTheWindow / 1.5 then set theWindowGroupIndex to the item (theIndex) of theWindowGroupIndices repeat with thePair in theOverlappingPairs if thePair's FirstWindowIndex = theIndex then if thePair's xRange ≥ theNearestNeighborXRange then set theIndexOfTheOther to thePair's theOtherOneOf(theIndex) set theHeightOfTheWindow to the (item 4 of theBounds) - the (item 2 of theBounds) set theWindowGroupIndexOfTheOther to the item (theIndexOfTheOther) of theWindowGroupIndices set theOverlappingYRange to ¬ me's calculateOverlappingYRange(theBounds, ¬ the item (theIndexOfTheOther) of theBoundsList) if theOverlappingYRange < theHeightOfTheWindow / 3 then if theWindowGroupIndex = 0 then if theWindowGroupIndexOfTheOther ≠ 0 then set the item (theWindowGroupIndexOfTheOther) of theWindowGroups to the item (theWindowGroupIndexOfTheOther) of theWindowGroups & {theIndex} set the item (theIndex) of the theWindowGroupIndices to theWindowGroupIndexOfTheOther else set the item (theIndex) of theWindowGroups to the item (theIndex) of theWindowGroups & {theIndex, theIndexOfTheOther} set the item (theIndex) of theWindowGroupIndices to theIndex set the item (theIndexOfTheOther) of theWindowGroupIndices to theIndex set theRealNumberOfWindowGroups to theRealNumberOfWindowGroups + 1 end if else if theWindowGroupIndexOfTheOther = 0 then set the item (theWindowGroupIndex) of theWindowGroups to the item (theWindowGroupIndex) of theWindowGroups & {theIndexOfTheOther} set the item (theIndexOfTheOther) of the theWindowGroupIndices to theWindowGroupIndex end if end if set unpaired to false end if end if end if end repeat end if if unpaired then set the item (theIndex) of theWindowGroups to the item (theIndex) of theWindowGroups & {theIndex} set the item (theIndex) of the theWindowGroupIndices to theIndex set theRealNumberOfWindowGroups to theRealNumberOfWindowGroups + 1 end if end repeat set theAverageWidthOfTheWindow to theAverageWidthOfTheWindow / (the count of theBoundsList) if theRealNumberOfWindowGroups > 0 then set theGridWidth to ((the item 3 of theWorkspaceBounds) - (the item 1 of theWorkspaceBounds) - theAverageWidthOfTheWindow) / (theRealNumberOfWindowGroups - 1) if theGridWidth > theAverageWidthOfTheWindow then set theGridWidth to theAverageWidthOfTheWindow set theGridIndex to 0 repeat with theIndex in theWindowIndicesSortedByPos set theIndex to the item (theIndex) of theWindowGroupIndices if the item (theIndex) of theWindows is not null then set theGroup to the item (theIndex) of theWindowGroups if the (count of theGroup) > 0 then set theBounds to the item (the first item of theGroup) of theBoundsList set theWidthOfTheWindow to the (item 3 of theBounds) - (the item 1 of theBounds) repeat with theWindowIndex in theGroup set theWindow to the item (theWindowIndex) of theWindows set thePosition to the position of theWindow set the item 1 of thePosition to theGridWidth * theGridIndex + the (item 1 of theWorkspaceBounds) set the position of theWindow to thePosition set the index of theWindow to theIndex end repeat set the item (theIndex) of theWindows to null set theGridIndex to theGridIndex + 1 end if end if end repeat end if end tell