The Omni Group Forums

The Omni Group Forums (http://forums.omnigroup.com/index.php)
-   OmniGraffle General (http://forums.omnigroup.com/forumdisplay.php?f=10)
-   -   Applescript to re-order objects by x,y coords? (http://forums.omnigroup.com/showthread.php?t=29591)

ericscheid 2013-05-15 08:40 PM

Applescript to re-order objects by x,y coords?
 
Has anyone already written up an AppleScript that will re-layer a selection of objects such that they are layered according to their vertical position?

With the item at the smallest y coord being behind all the rest, the next y-coord item being in front of that, and so on through to the item with the greatest y-coord being in front of all.

(Yikes, not easy to describe without getting confused about highest, top, down and up, and so on ;-)

RobTrew 2013-05-17 02:46 AM

Not sure how legible this is, but at one point of this function it passes a textual list of shape IDs with coordinates to a numeric sort on those coordinates. It then uses the ids to retrieve a list of shapes in spatial order.

[CODE]-- GET THE CHILDREN OF THE NODE IN THEIR LEFT RIGHT (OR TOP DOWN) SEQUENCE
-- (The OG Applescript library doesn't expose outline structure,
-- so we have to assume that Automatic Layout has been run, so that we can read the sibling sequence spatially)
on GetChildren(oParent, iAxis)
tell application id "OGfl"
-- Create a textual list of fields ID + horiz or vert position
set {lstOrigin, lstID} to {origin, id} of (destination of outgoing lines of oParent)

set strRows to ""
set lngID to length of lstID
repeat with i from 1 to lngID
set strRows to strRows & (item iAxis of (item i of lstOrigin)) & tab & item i of lstID & linefeed
end repeat

if strRows ≠ "" then
set lstID to paragraphs of (do shell script "echo " & quoted form of (texts 1 thru -2 of strRows) & " | sort -n | cut -f 2")

set lstChiln to {}
tell canvas of oParent
repeat with strID in lstID
set lngID to strID as integer
if not (plstSeen contains lngID) then

set end of plstSeen to lngID
set oChild to shape id lngID
set end of lstChiln to {oChild, my GetChildren(oChild, iAxis)}
end if
end repeat
end tell
return lstChiln
else
return {}
end if
end tell
end GetChildren
[/CODE]

ericscheid 2013-05-26 05:33 PM

Thanks, that's given me some leads.

One bugfix:

[CODE]
set lstChiln to {}
set plstSeen to {} -- ADD THIS MISSING LINE
tell canvas of oParent
[/CODE]

ericscheid 2013-05-26 06:48 PM

Here's my working script

[code]
-- relayers items of the selection according to their Y (vertical) coordinate
-- select all the items you want brought to front

tell application id "OGfl"
tell front window

-- get a text list of Y coord & object ID
set theSelection to the selection
if theSelection is not {} then
set theText to ""
repeat with theItem in theSelection
set theOrigin to origin of theItem
set theY to item 2 of (theOrigin)
set theID to the id of theItem
set theText to theText & theY & tab & theID & linefeed -- use linefeed, not return!
end repeat

-- sort the text list
set sortedIDs to paragraphs 2 through -1 of
(do shell script "echo " & quoted form of (theText) & " | sort -n | cut -f 2")

-- bring each to front, in sorted sequence
set refGraphics to (a reference to graphics of its canvas)
repeat with theID in sortedIDs
set oGraphic to (a reference to graphic id (theID as number))
move oGraphic to beginning of refGraphics
end repeat

else
beep
end if
end tell
end tell
[/code]

RobTrew 2013-05-26 11:15 PM

[QUOTE=ericscheid;124639]
[CODE]
set lstChiln to {}
set plstSeen to {} -- ADD THIS MISSING LINE
tell canvas of oParent
[/CODE][/QUOTE]

FWIW declaring large lists as script-level properties rather than local variables seems to improve their performance in Applescript.

(Hence the absence of a declaration for that list property within the function I should probably have pasted a preceding property declaration for you to make it a bit clearer).

ericscheid 2013-05-27 03:40 PM

Ah ok. Good tip.

Oh, that's what "p" "lst" probably means too =)

The script as it stands throws an error of "[I]The variable plstSeen is not defined[/I]" at the line [I]if not (plstSeen contains lngID) then[/I]

ericscheid 2013-05-27 04:46 PM

Oh, just realised it needs to be a property since it's a list of all nodes seen so far (to avoid cross links revisiting), not just nodes seen in this particular calling of the function, and thus needs to store values across multiple calls and recursive calls.

So, example code might be

[code]
on run
tell application id "OGfl"
tell front window
set theSelection to the selection
if theSelection is not {} then
set plstSeen to {} -- initialise for a new tree
set theResult to my GetChildren(item 1 of theSelection, 2)
end if
end tell
end tell
end run

property plstSeen : {} -- persistent storage of seen nodes
on GetChildren(oParent, iAxis)
-- etc
end GetChildren
[/code]


All times are GMT -8. The time now is 04:46 PM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2021, vBulletin Solutions, Inc.