Re: Bulk replacement of text from spreadsheet or text file (& Python)
Wim Lewis <[email protected]>
| Newsgroups | gmane.comp.graphics.omnigraffle.user |
|---|---|
| Message-ID | <[email protected]> |
On Jan 7, 2009, at 5:29 AM, Mark Barclay wrote:
> Thanks so much, Wim. Those are great suggestions! I especially like
> the DOT
> import idea - that opens up a lot of possibilities for getting some
> hierarchical formatting almost for free.
DOT is really handy for this; it's my usual way of getting data into
OmniGraffle if I just want to quickly visualize some graph or structure.
> since I know Python pretty well and like it very much (but have not
> used it
> on the Mac), I think I'll try the Python way. I have XCode installed
> and
> have looked briefly at its Python support. So...
>
> Can anyone please point me to some python sample code that connects
> through
> AppleScript, to a running instance of OmniGraffle, and creates a
> rectangle
> with the word "foo" as it's text? In fact any sample code at all
> that talks
> to OG would be a great starting point - I'm sure I could figure out
> the
> specifics of creating objects easily from there.
There is, as the Perl folks say, more than one way to do it. Probably
the simplest-to-implement way is to create an AppleScript script using
any tool you like, and pipe it into the 'osascript' command-line tool.
You can get an idea of how to produce various results by mocking them
up in an OmniGraffle document and then using 'Edit>Copy
As>AppleScript'. (The generated script isn't always perfect, but I
find it to be a good starting point.)
Or you can convert your data to some format that you can deal with
more directly in AppleScript --- Ian Piper's XML importer is a good
example of that.
I'm really fond of the "appscript" module in Python (it has
equivalents in Ruby and, I think, Perl). It lets you talk AppleEvents
directly, without an AppleScript layer in between, but still lets you
use the textual names supplied by the application's AppleScript
dictionary rather than cryptic AppleEvent FourCharCodes.
(A little bit of explanation: AppleScriptable applications don't
actually run an AppleScript interpreter. They respond to AppleEvents,
which are sort of language-neutral --- originally, they were intended
to be both programming-language-neutral and human-language-neutral.
The AppleScript interpreter (which is not running in the target
application, but instead running inside Script Editor or osascript or
another application) handles the control flow, variables, and so on,
as well as mapping the human-language class and property names to the
32-bit identifiers used in AppleEvents.)
So, anyway, here's an example of using appscript:
from appscript import *
og = app('OmniGraffle Professional 5') # lots of ways to specify the
application, check the appscript docs
ogdoc = og.make( new = k.document )
# The 'new' argument indicates the class of object to create a new
instance of
# the 'k' object is how to specify application scripting terminology
keywords in python; they're resolved to 4CCs when the event is
actually sent
# At this point ogdoc is something like: app('/Applications/Local/
OmniGraffle Professional 5.app').documents[u'Untitled']
c = ogdoc.canvases[0] # the document's (only) canvas, for convenience
# Make a couple of shapes
shape1 = c.make( new = k.shape );
# --> app(...).documents[u'Untitled'].canvases.ID(1).graphics.ID(3)
# also try shape1.properties() here to see all its properties
shape1.size.set( [ 35, 35 ] )
shape1.text.set( 'I am shape 1' )
shape1.name.get() # returns 'Rectangle', the default shape
shape2 = c.make( new = k.shape, with_properties = { k.name : 'Circle',
k.autosizing: k.full, k.text: 'Shape #2' } )
shape2.draws_shadow.set( k.false )
# connect them. This is an example of sending a command other than
make/get/set.
connection = shape1.connect( to = shape2 )
# returns the connecting line graphic
# --> app(...).documents[u'Untitled'].canvases.ID(1).graphics.ID(5)
connection.head_type.set( 'Arrow' )
# lay out the result
c.layout()
# save the document
ogdoc.save( ) # brings up a save panel since it's Untitled
# or: ogdoc.save( in_ = '/tmp/something' ) # saves it to /tmp/
something.graffle
# an example of exporting the document
og.current_export_settings.area_type.set( k.all_graphics )
ogdoc.save( in_ = '/tmp/woo', as_ = 'PNG' )
Appscript is here:
http://appscript.sourceforge.net/py-appscript/
One thing to be careful of is that these Python variables, like
AppleScript variables, hold object specifiers, not "hard" references
to actual objects. So if you have a variable that specifies a document
or canvas by name, for example, and you save it to another filename,
that variable will no longer be useful (you'll get a "can't get
reference" error, IIRC). Some kinds of specifiers, like ID specifiers,
are more persistent than others.