The previous version of the script did not handle package files. There were two problems:
- a package is basically a folder (trailing ":" or "/"), so exported files were created as file.graffle/.png, and
- OG 4.1.2 has a "bug" in that its 'documents whose path ...' strips the trailing "/", which confuses the find-the-document-we-just-opened logic. I just loooove Applescript.
I've had to strip some comments to keep under the 10,000 character limit. Does Omni have a better place to contribute AS code to?
Code:
-- Watch and auto-export OmniGraffle files to web-friendly versions
-- files/folders to watch are to be dropped onto this script (saved as a Stay Open application)
-- if a folder is watched all OG files in the folder will be monitored
-- exported files are created alongside the originals, named with the export_format extension
-- multiple-canvas documents are exported as per the 'Entire Document' (subdirectory named after the OG file)
-- based on / hacked from the original from Greg Titus (http://forums.omnigroup.com/showthread.php?p=537)
-- Changelog:
-- 2006-04-19 BDL added multiple canvases
-- 2006-04-21 BDL removed per-canvas exporting (window flipping is too intrusive), replaced
-- with export area = entire document; much mucking about with 'save in file'/folder business
-- 2006-05-17 BDL added "support" for OG package files
-- a file extension which Graffle supports for export
property export_format : "png"
-- amount of time to wait in between checking for file changes
-- this is adaptive, and is reset to 10s when a change is detected and will ramp up to 300s
property idle_time : 10
property idle_time_min : 10
property idle_time_max : 300
property idle_time_inc : 5
-- list of 'aliases' (folders, files) to watch (added to via 'on open')
property watch_files : {}
property watch_folders : {}
on run
set t to "OmniGraffle Auto-Exporter" & return & ¬
"Drop files/folders to be monitored on this script and they'll be automatically exported to " & export_format & ¬
" versions." & return & return & ¬
"This script will stay open whilst OmniGraffle is running." & return
set t to t & "Currently monitoring " & (count watch_files) & " file(s) and " & (count watch_folders) & " folder(s). "
if (count watch_files) > 0 or (count watch_folders) > 0 then
set r to button returned of (display dialog t & "Keep these?" buttons {"Yes", "No", "Show"} default button "Yes" with icon note)
if r is "Show" then
tell application "Finder"
activate
reveal {watch_files, watch_folders} -- one hit, so they're all selected
end tell
end if
if r is "No" then
set watch_files to {}
set watch_folders to {}
end if
else
display dialog t buttons {"Ok"} with icon note
end if
end run
on open item_list
tell application "Finder"
repeat with this_item in item_list
-- need to be careful of the list operations on watch_files, watch_folders - make sure only to add aliases
-- e.g. 'copy this_item to end of watch_files' corrupts the list on the second iteration, whereas
-- 'copy (this_item as alias) to end of watch_files' works fine
-- think you can find documentation on this? hah! (the Wikipedia AppleScript page was the
-- only reference I found that actually stated that 'on open' returns a list of aliases!)
if kind of this_item is "OmniGraffle document" then
if this_item is not in watch_files then copy (this_item as alias) to end of watch_files
else if kind of this_item is "folder" then
if this_item is not in watch_folders then copy (this_item as alias) to end of watch_folders
end if
end repeat
end tell
end open
on idle
-- if omnigraffle's not already running, close it after exporting the new files
tell application "System Events"
set isRunning to (name of processes) contains "OmniGraffle Professional"
end tell
tell application "Finder"
-- gather list of files to update
set file_list to watch_files
repeat with this_folder in watch_folders
-- display dialog "processing " & (this_folder as string) & "|" & class of this_folder
-- 'files of' ... returns 'class docf' (file?) objects, not aliases
set folder_files to (files of this_folder whose kind is "OmniGraffle document")
repeat with this_file in folder_files
set this_file to (this_file as alias)
--display dialog "f: " & this_file & "|" & class of this_file
if this_file is not in file_list then copy this_file to end of file_list
end repeat
end repeat
end tell
-- ok, now have list of candidate OG files (aliases)
set processed_items to false
repeat with this_file in file_list
set processed_items to my process_item(this_file, export_format)
end repeat
if not isRunning and processed_items then -- will have started up OG, so close it
tell application "OmniGraffle Professional"
-- close the app (if there are no open files, which there shouldn't be, as OG wasn't running before we started it)
--display dialog "ndocs: " & (count (document's modified))
if (count (document's modified)) is 0 then
quit
end if
end tell
end if
-- if files are being changed drop back to a fast idle time, otherwise decay
if processed_items then
set idle_time to idle_time_min
else
set idle_time to idle_time + idle_time_inc
if idle_time > idle_time_max then
set idle_time to idle_time_max
end if
end if
return idle_time
end idle
on process_item(source_file, export_format)
set processed_items to false
-- file extension must be added to the destination filename, and must match the export
-- type (i.e. 'save doc as "png" in file "figure.graffle.png"')
-- Note when saving a multi-page document, the destination filename will have the
-- export type extension removed, but *will not* have the .graffle extension removed. The
-- result will be created as the directory to hold the exported canvas files.
-- e.g. if destination = figure.graffle.png => OG will try to create figure.graffle/, but will fail as
-- this is the name of the source file!
-- OG strips the .graffle extension for the directory name automatically via the GUI, but not via AS
-- simple solution: double up the extension (figure.graffle.png.png => figure.graffle.png/...) when saving
-- (see export_item())
-- ok, now to really complicate matters: some OG files are folders (packages) i.e. file.graffle may
-- actually be ":path:to:file.graffle:"
-- - this stuffs up the export naming, so need to chomp any trailing path separators for package files
-- note that there's no point trying to do chomp the alias, as AS will gleefully put back the ":"
if package folder of (info for source_file) is true then
-- package, chomp trailing ':'
set new_name to (characters 1 through -2 of (source_file as string)) as string
set new_name to new_name & "." & export_format
else
-- plain file
set new_name to (source_file as string) & "." & export_format
end if
-- test if the target (new_name) needs to be updated
tell application "Finder"
-- if doesn't exist, need to update
set need_update to not (exists item new_name)
if not need_update then -- exists, but is it stale?
--display dialog "target mod date: " & (modification date of item new_name)
set need_update to modification date of source_file > modification date of item new_name
end if
end tell
if need_update then
my export_item(source_file, new_name, export_format)
set processed_items to true
end if
return processed_items
end process_item
-- this sub-routine does the export
on export_item(source_file, new_name, export_format)
with timeout of 900 seconds
tell application "OmniGraffle Professional"
set oldAreaType to area type of current export settings
-- open the file if it isn't already open
-- 1. convert the source_file alias to a POSIX path ("/path/to/file.graffle")
-- - OG's 'document path' property is a POSIX path
-- 2. see if a file with that path is currently open
-- 3. if not, open it
-- 4. get a reference to the document object
set the source_item to the POSIX path of the source_file
-- OG 4.1.2 returns 'path of...' WITHOUT the trailing slash for package files, need to
-- chomp before we compare ('documents whose path is ...')
if (package folder of (info for source_file) is true) and (character -1 of source_item is "/") then
-- package, chomp trailing '/'
set source_item to (characters 1 through -2 of source_item) as string
end if
set needToOpen to (count (documents whose path is source_item)) is 0
if needToOpen then
open source_file
end if
set theDocument to first item of (documents whose path is source_item)
-- single or multipage?
if (count of canvases of theDocument) = 1 then
set area type of current export settings to all graphics
else
set area type of current export settings to entire document
-- double up target directory name
set new_name to new_name & "." & export_format
end if
save theDocument as export_format in file new_name
-- if the file wasn't already open, close it again
if needToOpen then
close theDocument
end if
set area type of current export settings to oldAreaType
end tell
end timeout
end export_item