View Single Post
Quote:
Originally Posted by vinyl_warrior View Post
Is there a way to make it so that if the currently selected task were a child task (ie. a task within a subproject) then the script would change the parent task and not the project. Basically, to get the script to toggle the status of the project/subproject that is one up from what it is currently selected.
Here is a redraft which can be fine-tuned by setting two properties at the top of the script:
  1. pblnImmediateParentOnly
  2. pblnAllDescendantsInherit

If pblnImmediateParentOnly is set to TRUE, only the immediately selected object (or its immediate parent (task or project) if it is a childless leaf task) is the root of the toggle.
If pblnImmediateParentOnly is set to FALSE, the root of the toggle is the selected project, or the project containing the selection.

If pblnAllDescendantsInherit is set to TRUE, the specified root node (a project or a parent task) is toggled, and all of its descendants, unto the last generation, inherit its new parallel/sequential setting.
If pblnAllDescendantsInherit is set to FALSE, then only the immediate node is toggled, and any contained parent tasks retain their settings.

(A rough draft, I recommend a little testing and experimentation on dummy data before you start to use it)

Code:
-- Toggles selected project(s) / or parent task(s) between parallel and sequential
-- The root of the toggle may be the project or the immediate parent task
-- The result of the toggle may optionally be inherited by all descendants

-- See the settings of the following two boolean properties:

-- If TRUE the root of the toggling is the selected project
-- or selected parent task
-- or the immediate parent of the selected leaf task
-- if FALSE the root of the toggling is the selected PROJECT
-- or the PROJECT containing the selected task
property pblnImmediateParentOnly : true

-- If TRUE the root node is toggled, and ALL its descendants inherit the 
-- the new status, down to the last generation
property pblnAllDescendantsInherit : false


tell application "OmniFocus"
	set oWin to front document window of default document
	set lstSeldObjects to my SelectedObjects(oWin)
	
	set lstParents to {}
	repeat with oObject in lstSeldObjects
		set cClass to class of oObject
		if cClass is project or cClass is task then
			if cClass is project then
				set oParent to oObject
			else -- cClass is Task
				if pblnImmediateParentOnly then
					if (count of tasks of oObject) > 0 then
						set oParent to oObject
					else
						set oParent to container of oObject
					end if
				else -- Toggle the project of this task
					set oParent to containing project of oObject
				end if
			end if
			if not my IsMember(oParent, lstParents) then set end of lstParents to oParent
		end if
	end repeat
	
	-- toggle each specified parent of tasks
	repeat with oParent in lstParents
		set blnNewState to not sequential of oParent
		my SetState(oParent, blnNewState)
	end repeat
end tell


-- Toggles the status of the project or parent task,
-- and optionally (depending on the value of pblnAllDescendantsInherit)
-- propagates the new state down to the last generation of descendants
on SetState(oObject, blnNewState)
	using terms from application "OmniFocus"
		tell oObject
			set sequential to blnNewState
			if pblnAllDescendantsInherit then
				set lstTasks to tasks
				repeat with oTask in lstTasks
					my SetState(oTask, blnNewState)
				end repeat
			end if
		end tell
	end using terms from
end SetState

-- List of objects selected in the window
on SelectedObjects(oWin)
	using terms from application "OmniFocus"
		tell oWin
			set refSeln to a reference to (selected trees of content)
			if (count of refSeln) < 1 then ¬
				set refSeln to a reference to (selected trees of sidebar)
			if (count of refSeln) < 1 then return {}
			value of refSeln
		end tell
	end using terms from
end SelectedObjects


-- Simple test for list membership
-- used to ensure that we don't toggle the same project twice
on IsMember(oElement, lstList)
	using terms from application "OmniFocus"
		repeat with oItem in lstList
			if id of oItem is id of oElement then return true
		end repeat
		false
	end using terms from
end IsMember

Last edited by RobTrew; 2010-06-24 at 11:06 PM.. Reason: Updated comments in code