The Omni Group
These forums are now read-only. Please visit our new forums to participate in discussion. A new account will be required to post in the new forums. For more info on the switch, see this post. Thank you!

Go Back   The Omni Group Forums > OmniGraffle > OmniGraffle General
FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
Applescript to re-order objects by x,y coords? Thread Tools Search this Thread Display Modes
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 ;-)
 
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
 
Thanks, that's given me some leads.

One bugfix:

Code:
…
set lstChiln to {}
set plstSeen to {} -- ADD THIS MISSING LINE
tell canvas of oParent
…
 
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
 
Quote:
Originally Posted by ericscheid View Post
Code:
…
set lstChiln to {}
set plstSeen to {} -- ADD THIS MISSING LINE
tell canvas of oParent
…
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).
 
Ah ok. Good tip.

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

The script as it stands throws an error of "The variable plstSeen is not defined" at the line if not (plstSeen contains lngID) then
 
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
 
 


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes



All times are GMT -8. The time now is 07:51 AM.


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