View Single Post
Okay, my next actions list for today revealed entirely too many tasks involving cleaning the house and other intractable goals, so that seemed like a natural cue to do some Applescript instead :-)

The following script will capture the window positions and perspectives of your document windows and emit a script to the clipboard that will attempt to replicate your setup. I don't make any promises that it will do what you want with windows that aren't displaying a perspective, or windows where you've focused on something other than what the perspective requests. I think it should do the right thing with multiple monitors, but have no easy way to test that at the moment. If you find it deficient in any way, you know where the sources are, knock yourself out :-)

Code:
(*
   Capture OmniFocus Workspace
   
	This script generates an Applescript on the clipboard which will attempt to replicate the current document window placement(s) and perspective(s).  
	Paste the script into an Applescript editor, save, install in the OmniFocus scripts folder, add to the toolbar to have one-click access.
	Does not currently handle capturing focus state; create an additional perspective that shows only that subset if you need it.  Assumes all 
	windows are using perspectives!
	
	by Bill Palmer
	
	Copyright © 2010, Bill Palmer
	
	All rights reserved.
	
	Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
	
		• Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
		
		• Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
		
	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
	
	Version History:
	
		0.1, initial release, 11/6/10

*)

global _windowLst
property _boilerPlate1 : "
tell application id \"com.omnigroup.omnifocus\"
	tell front document
		repeat while ((count of document windows) > 1)
			set _window to first document window
			close _window
		end repeat
		set _lastRemainingWindow to first document window
"
property _boilerPlate2 : "
		close _lastRemainingWindow
	end tell
end tell
"

tell application id "com.omnigroup.omnifocus"
	set _windowLst to ""
	set _useExtract to my testBrokenPerspectiveNameReturn()
	tell front document
		repeat with _window in document windows
			set _bounds to bounds of _window
			if _useExtract then
				set _name to my extractPerspectiveName(name of _window)
			else
				set _name to perspective name of _window
			end if
			my appendWindowDetails(_bounds, _name)
		end repeat
	end tell
	tell application id "com.apple.finder" to set the clipboard to _boilerPlate1 & _windowLst & _boilerPlate2
end tell

-- append Applescript command to create specified window 
on appendWindowDetails(_bounds, _name)
	set _makeDir to "		make new document window at after front document window with properties {bounds:{" & item 1 of _bounds & "," & item 2 of _bounds & "," & ¬
		item 3 of _bounds & "," & item 4 of _bounds & "}," & ¬
		"perspective name: \"" & _name & "\"}
"
	set _windowLst to _windowLst & _makeDir
end appendWindowDetails

-- Currently OmniFocus returns "missing value" when reading the 
-- perspective name property of a window.  Test for this lossage and signal if
-- alternate approach needs to be used.  Returns true if still broken.
on testBrokenPerspectiveNameReturn()
	set _return to true -- assume broken until proven otherwise
	try
		tell application id "com.omnigroup.omnifocus"
			tell front document
				set _window to make new document window at before front document window with properties {perspective name:"All Items"}
				if (perspective name of _window is missing value) then
					set _return to true
				else
					set _return to false
				end if
				close _window
			end tell
		end tell
	on error
		set _return to true -- play it safe
	end try
	
	return _return
end testBrokenPerspectiveNameReturn

-- Extract perspective name from a window title string such as "William perspective: (Focus: Cub scouts)"
-- Assumes perspective name does not contain ":" (though OmniFocus allows it)
-- Needed because OmniFocus 1.8 builds currently always return "missing value" when reading 
-- perspective name property of a window.

on extractPerspectiveName(windowTitle)
	set _result to ""
	try
		set oldDelims to AppleScript's text item delimiters -- save their current state
		set AppleScript's text item delimiters to {":"} -- declare new delimiters
		set _result to first text item of windowTitle
		set AppleScript's text item delimiters to oldDelims -- restore them
	on error
		set AppleScript's text item delimiters to oldDelims -- restore them in case something went wrong
	end try
	return _result
end extractPerspectiveName