The latest, latest, version.
Oh, and it now is meant to run continuously, and will slow down the polling interval when OG isn't running, and when no changes are detected (i.e. you're off doing something else).
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
-- 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
-- evidently there are two kinds of file references in AS: a Finder file reference, and an alias
-- apparently aliases are "more useful"
-- 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
(*
set s to ""
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {return & tab}
set s to s & "files: (" & (count of watch_files) & "): " & return
set s to s & tab & (watch_files as string) & return
set s to s & "folders: (" & (count of watch_folders) & "): " & return
set s to s & tab & (watch_folders as string) & return
display dialog s
set AppleScript's text item delimiters to tid
*)
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
(*
set s to ""
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {return & tab}
set s to s & "file_list: (" & (count of file_list) & "): " & return
set s to s & tab & (file_list as string) & return
display dialog s
set AppleScript's text item delimiters to tid
*)
end tell
-- ok, now have list of candidate OG files
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
-- don't double up yet, as we want to test the directory's modification time
set new_name to (source_file as string) & "." & export_format
-- test if the target (new_name) needs to be updated
tell application "Finder"
-- combining the test (exists AND mod date) fails when destination doesn't exist
-- why does AS execute the second statement when the first is false?
-- worse, why did that logic work earlier? (ref. Omni forum's original)
-- 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)
-- if there isn't an export file or if the graffle file is newer, do the export
with timeout of 900 seconds
tell application "OmniGraffle Professional"
-- if the file's being actively edited, a random object may be selected when we come to
-- do the export, and with an object selected the export will default to 'selected graphics' - oops!
-- sooo, we will explicitly set the area type (and return it later)
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
set needToOpen to (count (documents whose path is source_item)) is 0
if needToOpen then
open source_file
end if
-- you'd think open would return the document you just opened, no?
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