Friday, August 21, 2009

Applescripting with OmniGraffle: exporting all groups, draw some points

I haven't really spent a lot of time writing or using Applescript before. I dabbled only when I needed to tweak one that I'd found on the web. This is sensible since a web search is always a practical problem solver's first step in finding a solution. This is also due to my love of the Unix command line. If I need something quick and dirty then I write it in pipe and filter semantics with some command line voodoo using the likes of awk, sed, grep, tr, cut, paste, and sometimes add some Perl for good measure. After using Applescript for a few days and ruminating over its syntax, I think that it is crafty, compact, and extensible. Unlike most languages, it doesn't really 'do' anything. It is the laziest language I've come across and I like that. The way it works is to just literally 'tell' other applications what it wants done. It has data structures, and types (of sorts). And like many extensible languages, it suffers from a dearth of cohesive intelligible resources for understanding its use. Sure, there are books on Applescript, and lots of resources on the web, but a lot of basic things that should be covered (because of the downright weirdness of the language) are nowhere to be found. The dictionaries that are provided with each 'AppleScriptable' application provide the minimum information required with no examples of the use of particular objects or messages.

Nonetheless, this week I wrote three simple Applescripts for the OmniGraffle vector drawing application out of necessity. The first two export either all of groups or graphics of a OmniGraffle document as a particular format. This is useful if you create a large number of graphics that you want to export, or as I often do, create a large number of groups of graphics that each comprise an icon. There is no 'batch' export in OmniGraffle because they almost certainly figured that someone would just use Applescript to do it.

The third is even simpler; it just imports a comma-delimited list of value pairs as the endpoints of line segments. That is, it draws x-y coordinates as a single connected graphic.  The syntax for doing this can be learned by drawing something and then ->Edit->Copy As->Applescript....a very neat feature.

Just cut and paste the scripts below into the Script Editor and save them under ~/Library/Scripts/Applications/OmniGraffle (or OmniGraffle Pro)

OminGraffle export all groups
------------------------------------------------------------

--Copyright 2009, Sunny Fugate
--Creative Commons Attribution-Share Alike 3.0
--http://creativecommons.org/licenses/by-sa/3.0/us/
--
tell application "OmniGraffle Professional 5"
--Setup export options
set current export settings's area type to selected graphics
set current export settings's draws background to false
set current export settings's export scale to 1
set current export settings's include border to false
set current export settings's resolution to 2.0
--Retrieve the desired output export path
set myFolder to POSIX path of (choose folder)
--Get the desired output format
set outputTypeList to {"PDF", "TIFF", "PNG", "GIF", "JPEG", "EPS", "SVG", "PICT", "BMP"}
choose from list outputTypeList with prompt "Choose export format"
set exportformat to result as text
--Get the desired file prefix
set prefixDialog to display dialog "Enter a desired output file prefix or leave blank" default answer ""
set filePrefix to the text returned of prefixDialog
--Get the current document for later use
set currentDocument to document of front window
--Get a list of the canvases
set theCanvases to every canvas of currentDocument
--Use a counter for unique naming
set counter to 0
--Loop over each canvas
repeat with aCanvas in theCanvases
--Make sure that the current canvas is displayed 
--(export of currently selected only works in the displayed window
set canvas of front window to aCanvas
--get a list of groups for this canvas
set theGroups to every group of aCanvas
get theGroups
--loop over each group
repeat with aGroup in theGroups
get aGroup
--Set the selection of the window and save / export
set selection of front window to {aGroup}
save currentDocument as exportformat in POSIX file (myFolder & filePrefix & (counter))
set counter to counter + 1
end repeat
end repeat
end tell


OmniGraffle export all graphics
--------------------------------------------

--Copyright 2009, Sunny Fugate
--Creative Commons Attribution-Share Alike 3.0
--http://creativecommons.org/licenses/by-sa/3.0/us/
--
tell application "OmniGraffle Professional 5"
--Setup export options
set current export settings's area type to selected graphics
set current export settings's draws background to false
set current export settings's export scale to 1
set current export settings's include border to false
set current export settings's resolution to 2.0
--Retrieve the desired output export path
set myFolder to POSIX path of (choose folder)
--Get the desired output format
set outputTypeList to {"PDF", "TIFF", "PNG", "GIF", "JPEG", "EPS", "SVG", "PICT", "BMP"}
choose from list outputTypeList with prompt "Choose export format"
set exportformat to result as text
--Get the desired file prefix
set prefixDialog to display dialog "Enter a desired output file prefix or leave blank" default answer ""
set filePrefix to the text returned of prefixDialog
--Get the current document for later use
set currentDocument to document of front window
--Get a list of the canvases
set theCanvases to every canvas of currentDocument
--Use a counter for unique naming
set counter to 0
--Loop over each canvas
repeat with aCanvas in theCanvases
--Make sure that the current canvas is displayed 
--(export of currently selected only works in the displayed window
set canvas of front window to aCanvas
--get a list of groups for this canvas
set theGroups to every graphic of aCanvas
get theGroups
--loop over each group/graphic
repeat with aGroup in theGroups
get aGroup
--Set the selection of the window and save / export
set selection of front window to {aGroup}
save currentDocument as exportformat in POSIX file (myFolder & filePrefix & (counter))
set counter to counter + 1
end repeat
end repeat
end tell


OmniGraffle draw line from clipboard


--------------------------------------------
--Copyright 2009, Sunny Fugate
--Creative Commons Attribution-Share Alike 3.0
--http://creativecommons.org/licenses/by-sa/3.0/us/
--
--Expect values to be comma delimited x,y with linebreak between each value
set theData to the clipboard
set AppleScript's text item delimiters to (ASCII character 13)
set valueList to every text item of theData
--set numberString to "{"
set numberList to {}
set AppleScript's text item delimiters to {","}
repeat with value in text items of valueList
--stupid extra repeat which never repeats to emulate a repeat 'next/continue'
repeat while true
try
set x to item 1 of text items of value as number
set y to item 2 of text items of value as number
on error theError number errorNum
exit repeat
end try
set numberList to numberList & {{x, y}}
exit repeat
end repeat
end repeat
tell application "OmniGraffle Professional 5"
tell canvas of front window
make new line at end of graphics with properties {point list:numberList}
end tell
end tell