
require 'todo_a'
require 'outline_html'
require 'benchmark'

class ActionBrowser < NSObject

	attr_accessor :browserWindow, :filterView, :filterController, :outlineView, :outlineController, :taskView, :taskController, :contextController
	attr_accessor :pickerPicker, :pickerView, :pickerLabel, :emailText
	attr_accessor :quickSplitView, :deferView, :quickSplitText, :deferDate, :splitLabel
	
	attr_accessor :filterSets,:tasks,:rootActions,:atdFilter, :atdControl, :splitViewV,:splitViewH, :filterGroup, :contextPopup, :projectPopup, :projectController
	
	attr_accessor :focus
	
	attr_accessor :allCountView,:ableCountView,:todoCountView,:doneCountView
	
	kvc_accessor :todoCount,:actionableCount,:doneCount,:allCount
	
	@@columnNames={ "name"=>"Name",
	        "done"=>"Done",
	        "note"=>"Note",
	        "context"=>"Context",
	        "project"=>"Project",
	        "important"=>"Important",
	        "urgent"=>"Urgent",
	        "createDate"=>"Creation Date",
	        "startDateDate"=>"Start Date",
	        "doDateDate"=>"Do On Date",
	        "dueDateDate"=>"Due Date",
	        "startDateDateOrNil"=>"Start Date",
	        "doDateDateOrNil"=>"Do On Date",
	        "dueDateDateOrNil"=>"Due Date",
	        "startDateTime"=>"Start Time",
	        "doDateTime"=>"Do On Time",
	        "dueDateTime"=>"Due Time",
	        "startDateTimeOrNil"=>"Start Time",
	        "doDateTimeOrNil"=>"Do On Time",
	        "dueDateTimeOrNil"=>"Due Time",
	        "finishDate"=>"Finish Date",
	        "recur"=>"Recurring?",
	        "recurReset"=>"Reset recur?",
	        "recurDays"=>"Recur Days",
	        "recurDeadline"=>"Recur Deadline",
	        "someday"=>"Someday?",
	        "template"=>"Template?",
	        "area"=>"Area?",
	        }
	@@columnPaths={ "name"=>"name",
	        "done"=>"done",
	        "note"=>"noteString",
	        "context"=>"context.name",
	        "project"=>"parent.name",
	        "important"=>"isImportant",
	        "urgent"=>"isUrgent",
	        "createDate"=>"createDate",
	        "startDate"=>"startDate",
	        "doDate"=>"doDate",
	        "dueDate"=>"dueDate",
	        "finishDate"=>"finishDate",
	        "recur"=>"isRecurring",
	        "recurReset"=>"recurReset",
	        "rreset"=>"recurReset",
	        "rReset"=>"recurReset",
	        "recurDays"=>"recurDays",
	        "recurDelay"=>"recurDays",
	        "recurDeadline"=>"recurDeadline",
	        "rdeadline"=>"recurDeadline",
	        "someday"=>"isSomeday",
	        "template"=>"isTemplate",
	        "area"=>"isArea",
	        }
	
	#kvc_accessor  :taskSortDescriptors,:outlineSortDescriptors
	@@dragTypes=["OutlineDrag"]
		
	def windowNib
		@windowNib ||= NSNib.alloc.initWithNibNamed_bundle('MainWindowL',nil)
	end
	
	def pickerNib 
		@pickerNib ||= NSNib.alloc.initWithNibNamed_bundle('ABPicker',nil)
	end
	
	def setup(appDelegate,nfocus=nil)
	  @appDelegate=appDelegate
		@atdFilter=0
		@focus=nfocus
		@allCount=0
		reset_newlyCreated
		windowNib.instantiateNibWithOwner_topLevelObjects(self,nil)
		browserWindow.setDelegate(self)
    #@outlineController.setRootObjectsArray(rootActions)
    @outlineController.setRootKeyPath("rootActions")
    @outlineController.setFilterPredicate(NSPredicate.predicateWithValue(true))
    @outlineView.setIsExpandedKeyPath("isExpanded")
    @outlineView.setIsExpandedFilteredKeyPath("isExpanded")
		@outlineView.setOutlineTableColumn(@outlineView.tableColumnWithIdentifier("name"))
		@outlineView.restoreCollapsedItems
		@outlineController.setSortDescriptors(outlineSortDescriptors)
		@outlineView.registerForDraggedTypes(@@dragTypes)
		@taskView.setDataSource(self)
		@taskView.registerForDraggedTypes(@@dragTypes)
		@taskView.setDraggingSourceOperationMask_forLocal(NSDragOperationEvery,true)
		@taskView.setDraggingSourceOperationMask_forLocal(NSDragOperationCopy,false)
		#@outlineView.setShouldEditNextItemWhenEditingEnds(false)
		#@outlineView.setTypeAheadSelectionEnabled(true)
		#@outlineView.setCreatesNewItemWithReturnKey(true)
		if @focus
		  @browserWindow.setTitle("#{focus[0].name} Focus") if focus.size==1
		  @browserWindow.setTitle("#{focus[0].name} and Friends Focus") if focus.size > 1
		else
		  @browserWindow.setTitle("Action Browser")
		end
		setupContextPopup
 		registerObservers
		@browserWindow.makeKeyAndOrderFront(nil)
	end
	
	def setupProjectPopup
	  menu=NSMenu.alloc.init
	  menuItem=NSMenuItem.alloc.init
	  menuItem.setTitle("---")
	  menu.addItem(menuItem)
	  contexts=@projectController.arrangedObjects.sort_by {|c| c.name.to_s }
	  contexts.each do |c| 
	    menuItem=NSMenuItem.alloc.init
	    menuItem.setTitle(c.name)
	    menuItem.setRepresentedObject(c)
	    menu.addItem(menuItem)
	  end
	  @projectPopup.setMenu(menu)
	end
	
	def setupContextPopup
	  menu=NSMenu.alloc.init
	  menuItem=NSMenuItem.alloc.init
	  menuItem.setTitle("-INBOX-")
	  menu.addItem(menuItem)
	  contexts=@contextController.arrangedObjects.sort_by {|c| c.name.to_s }
	  contexts.each do |c| 
	    menuItem=NSMenuItem.alloc.init
	    menuItem.setTitle(c.name) if c.name
	    menuItem.setRepresentedObject(c)
	    menu.addItem(menuItem)
	  end
	  @contextPopup.setMenu(menu)
	end
	def registerObservers
	  #@filterController.addObserver_forKeyPath_options_context(self,"selection",NSKeyValueObservingOptionNew,nil)
	  @contextController.addObserver_forKeyPath_options_context(self,"arrangedObjects",NSKeyValueObservingOptionNew,nil)
	  @projectController.addObserver_forKeyPath_options_context(self,"arrangedObjects",NSKeyValueObservingOptionNew,nil)
  end
  
  def atdAllClick(sender)
	@atdControl.selectSegmentWithTag(0)
	atdClick(@atdControl)
  end
  
  def atdAbleClick(sender)
	@atdControl.selectSegmentWithTag(1)
	atdClick(@atdControl)
  end
  
  def atdTodoClick(sender)
	@atdControl.selectSegmentWithTag(2)
	atdClick(@atdControl)
  end

  def atdDoneClick(sender)
	@atdControl.selectSegmentWithTag(3)
	atdClick(@atdControl)
  end

  def atdClick(sender)
    clicked=@atdControl.selectedSegment
    (0..3).each{|s| @atdControl.setSelected_forSegment(false,s) if s != clicked }
    filterSets
    @filterSets['Completion'].filters.each do |f|
      f.selected=0
    end
    filterChange #will build and set based on selected segments
  end
  
  def resetAtdFilter
    willChangeValueForKey "atdFilter"
    @atdFilter=0
    didChangeValueForKey "atdFilter"
  end
  
  def toggleOutlineCollapse(sender)
    return if RBSplitSubview.animating.to_i==1
    if (@splitViewH.subviewWithIdentifier("flat").isCollapsed?) && !(@splitViewH.subviewWithIdentifier("outline").isCollapsed?)
      ## task view is already collapsed, so this won't do anything. Have it switch instead.
      @splitViewH.subviewWithIdentifier("flat").toggleCollapseQuick(sender)
      @splitViewH.subviewWithIdentifier("outline").collapse
    else
      @splitViewH.subviewWithIdentifier("outline").toggleCollapse(sender)
    end
  end
  
  def toggleTaskCollapse(sender)
    return if RBSplitSubview.animating.to_i==1
    if (@splitViewH.subviewWithIdentifier("outline").isCollapsed?) && !(@splitViewH.subviewWithIdentifier("flat").isCollapsed?)
      ## outline view is already collapsed, so this won't do anything. Have it switch instead.
      @splitViewH.subviewWithIdentifier("outline").toggleCollapseQuick(sender)
      @splitViewH.subviewWithIdentifier("flat").collapse
    else
      @splitViewH.subviewWithIdentifier("flat").toggleCollapse(sender)
    end
  end
  
  def reset_newlyCreated
    @newlyCreated=Set.new
  end
  
  def showNote(sender)
    case sender.__ocid__
    when @outlineView.__ocid__
      note=sender.originalItemAtRow(sender.clickedRow)
	  @addOutline=true
    when @taskView.__ocid__
      note=@taskController.arrangedObjects.objectAtIndex(sender.clickedRow)
	  @addOutline=false
    end
    note.openNoteReader if note
  end
  
  def filterClick(sender)
    (0..3).each {|s| @atdControl.setSelected_forSegment(false,s) }
    sender=@filterView.itemAtRow(sender.clickedRow).representedObject
    sender.toggleSelected
    filterChange
  end
  
  def showInfo(sender)
  end
  
  def reset_filters
    @filterGroup = nil
    filterGroup
  end
  def reset_outline_visible
    reset_filters
    #@outlineController.setFilterPredicate(self)
    willChangeValueForKey "rootActions"
    willChangeValueForKey "tasks"
    @rootActions=nil
    @tasks=nil
    didChangeValueForKey "tasks"   
    didChangeValueForKey "rootActions"   
  end
  
  def reset_visible_actions
    $managedObjectContext.processPendingChanges
    reset_outline_visible
  end
  
  def filterChange
    reset_newlyCreated
    reset_visible_actions 
  end
  
  def observeValueForKeyPath_ofObject_change_context(keyPath,object,change,context)
    if keyPath.to_s == "selection"
      filterChange
    elsif keyPath.to_s == "arrangedObjects"
      setupContextPopup
      setupProjectPopup
    end
  end
	
	def managedObjectContext
	  @appDelegate.managedObjectContext
	end
	
	def processQuickEntry(sender)
	  newEntry=sender.stringValue
	  return if !newEntry || newEntry.length==0
	  print "Quick Entry: #{newEntry}\n"
	  newAction=createActionWithParentAtIndex(nil,0)
	  newAction.setParent(@focus[0]) if @focus && @focus.size==1
	  newAction.smartName= newEntry
	  newAction.setContext(newAction.parent.context()) if (newAction.parent? && !newAction.context? && newAction.parent.context?)
	  scrollToAction(newAction)
	  selectAction(newAction)
	  sender.setStringValue("")
	  newAction
	end
	
	def searchPredicate
	  @searchPredicate
	end
	
	def searchPredicate=(value)
	  willChangeValueForKey "searchPredicate"
	  @searchPredicate = value
	  didChangeValueForKey "searchPredicate"
	  @taskController.takeValue_forKey(@searchPredicate,"filterPredicate")
	  #@outlineController.setFilterPredicate(@searchPredicate? @searchPredicate: self) 
	  reset_outline_visible
	  ##reset_visible_actions #force recalc
	end
	
	def processCompletionFilter(sender)
	  reset_visible_actions #force recalc
	end
	
	def createActionWithParentAtIndex(parent,index)
	  newAction= NSEntityDescription.insertNewObjectForEntityForName_inManagedObjectContext("Action",managedObjectContext)
	  if parent
	    parent.bumpChildrenFromIndex_throughIndex(index,index+1) if index > parent.valueForKeyPath("children.@max.sequenceValue").to_i
	    newAction.sequenceValue= index
	    parent.addChildrenObject(newAction)
	    parent.resequence
	  end
	  willChangeValueForKey "tasks"
	  @tasks=nil 
	  didChangeValueForKey "tasks"
	  if !parent
	    willChangeValueForKey "rootActions"
	    @rootActions << newAction if @rootActions!=nil
	    didChangeValueForKey "rootActions"
	  else
		newAction.setContext(parent.context()) if (parent.context())
	  end
	  @newlyCreated << newAction
	  reset_visible_actions
	  newAction
	end
	
	def expandUp(action)
	    expandUp(action.parent) if (action.parent?)
	    @outlineView.expandItem(@outlineController.nodeForObservedObject(action)) if (!action.isExpanded?) && @outlineController.nodeForObservedObject(action)
	    @addOutline=true
	end
	
	def scrollTaskToAction(action)
	  row=@taskController.arrangedObjects.indexOfObject(action)
	  @taskView.scrollRowToVisible(row) if row != NSNotFound
	end
	def scrollOutlineToAction(action)
	  expandUp(action.parent) if (action.parent?)
	  row=@outlineView.rowForOriginalItem(action)
	  @outlineView.scrollRowToVisible(row) if row != NSNotFound
	end
	def scrollToAction(action)
	  expandUp(action.parent) if (action.parent?)
	  row=@outlineView.rowForOriginalItem(action)
	  @outlineView.scrollRowToVisible(row) if row != NSNotFound
	  row=@taskController.arrangedObjects.indexOfObject(action)
	  @taskView.scrollRowToVisible(row) if row != NSNotFound
	end
	
	def selectAction(result)
	  @outlineController.setSelectedObjects([result])
	  @taskController.setSelectedObjects([result])	  
	end
	
	def editAction(action)
      selectAction(action)
	  if @splitViewH.subviewWithIdentifier("outline").isCollapsed? && @splitViewH.subviewWithIdentifier("outline").isCollapsed?!=0
		@addOutline=false
	  else
		@addOutline=true if @addOutline==nil 
	  end
	  if (not @addOutline)
	    row=@taskController.arrangedObjects.indexOfObject(action)
	    @taskView.editColumn_row_withEvent_select(@taskView.columnWithIdentifier("name"),
  	      row,nil,true) if row != NSNotFound
	  else
	    row=@outlineView.rowForOriginalItem(action)
  	  @outlineView.editColumn_row_withEvent_select(@outlineView.columnWithIdentifier("name"),
  	      row,nil,true) if row != NSNotFound && row > 0
	  end
	end
	
	def addChildToOutline(sender)
		@addOutline=true
		addChild(sender)
	end
	
	def addSiblingToOutline(sender)
		@addOutline=true
		addSibling(sender)
	end

	def addChildToTasks(sender)
		@addOutline=false
		addChild(sender)
	end
	
	def addSiblingToTasks(sender)
		@addOutline=false
		addSibling(sender)
	end
	
	def addChild(sender)
	  taskController.commitEditing
	  #outlineController.commitEditing
	  sel=outlineController.selectedObjects
	  sel=taskController.selectedObjects if sel==nil ||  sel.count==0
	  sel=nil if sel==nil || sel.count==0
	  actionParent=sel[0] if sel != nil
	  index=0
	  index=sel[0].valueForKeyPath("children.@max.sequenceValue").to_i+1 if sel != nil
	  result=createActionWithParentAtIndex(actionParent,index)
	  scrollToAction(result)
	  selectAction(result)
	  result.setName("-Enter Action Name-")
	  editAction(result)
	  result
	end
	
	def addSibling(sender)
	  taskController.commitEditing
	  #outlineController.commitEditing
	  actionParent=nil
	  sel=outlineController.selectedObjects
	  sel=taskController.selectedObjects if sel==nil || sel.count==0
	  sel=nil if sel==nil || sel.count==0
	  actionParent=sel[0].parent if sel != nil
	  index=999
	  index=sel[0].sequenceValue.to_i+1 if actionParent != nil
	  result=createActionWithParentAtIndex(actionParent,index)
	  scrollToAction(result)
	  selectAction(result)
	  result.setName("-Enter Action Name-")
	  editAction(result)
	  result
	end
	
	def group(sender)
 	  taskController.commitEditing
	  #outlineController.commitEditing
	  actionParent=nil
	  sel=outlineController.selectedObjects
	  sel=taskController.selectedObjects if sel==nil || sel.count==0
	  sel=removeChildrenFromSelection(sel)
	  sel=nil if sel==nil || sel.count==0
	  actionParent=sel[0].parent if sel != nil
	  index=999
	  index=sel[0].sequenceValue.to_i+1 if actionParent != nil
	  result=createActionWithParentAtIndex(actionParent,index)
	  result.setName("-Enter Action Name-")
	  sel.each{|a| a.setParent(result)}
	  $managedObjectContext.processPendingChanges
	  scrollToAction(result)
	  selectAction(result)
	  editAction(result)
	  result
	end
	
	def ungroup(sender)
	  taskController.commitEditing
	  #outlineController.commitEditing
	  actionParent=nil
	  sel=outlineController.selectedObjects
	  sel=taskController.selectedObjects if sel==nil || sel.count==0
	  sel=removeChildrenFromSelection(sel)
	  sel=nil if sel==nil || sel.count==0
	  actionParent=sel[0].parent if sel != nil
	  index=999
	  index=sel[0].sequenceValue.to_i+1 if actionParent != nil
	  sel.each do |s|
	    kids=sel.kids
	    newParent=s.parent
	    index=sequencevalue.to_i+1
	    newParent.bumpChildrenFromIndex_throughIndex(index,index+kids.size) if newParent
	    kids.each do |k|
	      k.setParent(newParent)
	      k.setSequenceValue(index)
	      index=index+1
	    end
	    newParent.resequence
	  end 
	  $managedObjectContext.processPendingChanges
	end
	
	def deleteButton(sender)
	end
		
  def addFilter(result,f)
    result[f.category]= FilterCategory.alloc.init(f.category) unless result[f.category]
    result[f.category].addFilter(f)
  end
  def addFilters(result,filters)
    filters.each do |f|
      addFilter(result,f)
    end
  end

  def buildAllFilters(mc)
    result={}
    addFilters(result,ContextFilter::buildFilters(mc.objectsForEntityNamed('Context')))
    addFilters(result,TimeFilter::buildFilters())
    addFilters(result,AreaFilter::buildFilters(mc.objectsForEntityNamed('Action')))
    addFilters(result,PriorityFilter::buildFilters())
    addFilter(result,ActionableFilter.alloc.init())
    addFilter(result,NextFilter.alloc.init())
    addFilter(result,RecurringFilter.alloc.init())
    addFilter(result,SomedayFilter.alloc.init())
    addFilter(result,TaskFilter.alloc.init())
    addFilter(result,TemplateFilter.alloc.init())
    addFilter(result,CameFromEmailFilter.alloc.init())
    addFilter(result,SentEmailFilter.alloc.init())
    addFilter(result,DelegatedFromFilter.alloc.init())
    addFilter(result,DelegatedToFilter.alloc.init())
    addFilters(result,CompletionFilter.buildFilters())
    result
  end

	def filterSets
	  @filterSets = buildAllFilters(managedObjectContext) if !@filterSets
	  @filterSets.values
  end
  
  def showActionable(sender)
	@atdControl.setSelectedSegment(1)
	atdClick
  end
  def showToDo(sender)
	@atdControl.setSelectedSegment(2)
	atdClick
  end
  def showDone(sender)
	@atdControl.setSelectedSegment(3)
	atdClick
  end
  
  def mapFilterControl
    filterSets # force calc if not built
    @filterSets['Completion'].filters.each do |f| 
      case f.rawName
        when "Done"
          f.selected=1 if @atdControl.isSelectedForSegment?(3)
        when "To-Do"
          f.selected=1 if @atdControl.isSelectedForSegment?(2)
        when "Actionable"
          f.selected=1 if @atdControl.isSelectedForSegment?(1)
        else
          print "unknown completion filter #{f.name}\n"
      end
    end
    oneselected=false
    @filterSets['Completion'].filters.each do |f| 
      case f.rawName
        when "Done"
          if f.selected.to_i==1
            @atdControl.setSelected_forSegment(true,3)
            oneselected=true
          else
            @atdControl.setSelected_forSegment(false,3)
          end
        when "To-Do"
          if f.selected.to_i==1
            @atdControl.setSelected_forSegment(true,2)
            oneselected=true
          else
            @atdControl.setSelected_forSegment(false,2)
          end
        when "Actionable"
          if f.selected.to_i==1
            @atdControl.setSelected_forSegment(true,1)
            oneselected=true
          else
            @atdControl.setSelected_forSegment(false,1)
          end
        else
          print "unknown completion filter #{f.name}\n"
      end
    end
    @atdControl.setSelected_forSegment(true,0) if not oneselected
  end
  
  def updateCountViews
	allCountView.setStringValue("#{@allCount}") if @allCountView
	ableCountView.setStringValue("#{@actionableCount}") if @ableCountView
	todoCountView.setStringValue("#{@todoCount}") if @todoCountView
	doneCountView.setStringValue("#{@doneCount}") if @doneCountView
  end
  
  def filterGroup
    return @filterGroup if @filterGroup != nil
	timetaken=Benchmark.measure do
		mapFilterControl if (@atdControl) #atdControl may not be set yet from nib
		@filterList=[]
		filterSets.each do |c| 
		  c.filters.each do |f| 
			@filterList << f if f.selected.to_i !=0 
		  end
		end
		#@filterList.each {|f| resetAtdFilter if f.category=="Completion"} if (@atdFilter.to_i != 0)# UI tweak
		#sTasks=startingTasks.find_all{|a| a.isTask? && (@atdFilter.to_i != 1 || a.isActionable?) && (@atdFilter.to_i != 2 || a.done?)}
		sTasks=startingTasks.find_all{|a| a.isTask?}
		tTasks=sTasks.find_all{|a| !a.done? }
		dTasks=sTasks.find_all{|a| a.done? }
		aTasks=sTasks.find_all{|a| a.isActionable? }
		@todoCount=tTasks.size
		@actionableCount=aTasks.size
		@doneCount=dTasks.size
		@allCount=sTasks.size
		updateCountViews
#		filterSets.each do |c| 
#		  c.filters.each do |f| 
#			if f.category!="Completion"
#			  f.tcount=f.filterActions(tTasks).size 
#			  f.dcount=f.filterActions(dTasks).size 
#			  f.acount=f.filterActions(aTasks).size
#			else
#			  case f.rawName
#			  when "To-Do"
#				f.tcount=tTasks.size
#				f.dcount=0
#				f.acount=aTasks.size
#			  when "Actionable"
#				f.tcount=tTasks.size
#				f.dcount=0
#				f.acount=aTasks.size
#			  when "Done"
#				f.dcount=dTasks.size
#				f.tcount=0
#				f.acount=0
#			  end
#			end
#		  end 
#		end
		if (@filterList.size < 1)
		  @filterGroup = Set.new()
		else
		  @filterGroup=Set.new(@filterList).divide {|x| x.category}
		end
	end
	print "benchmarking filterGroup", timetaken
	pred = filterGroupPredicate
	@outlineController.setFilterPredicate(pred)

    @filterGroup
  end
  
  def filterGroupPredicate
	styles=filterGroup
	tops=[]
	tops << NSPredicate.predicateWithFormat("isTask == true")
	if (styles.size)
	    subs=[]
		styles.each do |s|
			s.each { |f| subs << f.predicate }
			tops << NSCompoundPredicate.orPredicateWithSubpredicates(subs)
		end
	end
	tops << @searchPredicate if @searchPredicate
	return NSCompoundPredicate.andPredicateWithSubpredicates_(tops) if tops.size
	return NSPredicate.predicateWithValue(true)
  end
  
  
  def evaluateWithObject?(obj)
	return testObject(obj) == true
  end
  
  def testObject(obj)
    styles=filterGroup
    result=true
    return true if @newlyCreated!= nil && @newlyCreated.include?(obj)
    if (styles.size)
      styles.each do |s|
        sresult = false
        s.each do |f|
          if f.showAction?(obj)
            sresult ||= true
            break
          end
        end
        result &&= sresult
        break if !result
      end
    end
    
    #result &&= obj.isActionable? if (@atdFilter.to_i==1)
    #result &&= obj.done? if (@atdFilter.to_i==2)
    result &&= @searchPredicate.evaluateWithObject?(obj) if @searchPredicate
    result
  end
  
  def filterTasks(actions)
	result = nil
	timetaken=Benchmark.measure do
		if (filterGroup.size < 1)
		  result=Set.new(actions.find_all{|a| a.isTask?}) #default is EVERYTHING
		  result=Set.new(result.to_a.find_all{|a| @searchPredicate.evaluateWithObject(a)}) if (@searchPredicate) 
		else
		  pred = filterGroupPredicate
		  result = Set.new(NSArray.arrayWithArray(actions).filteredArrayUsingPredicate(pred))
		  result += @newlyCreated if @newlyCreated
#		  result=Set.new(actions.find_all{|a| a.isTask? && testObject(a)})
		end
		#result=Set.new(result.to_a.find_all{|a| a.isActionable?}) if (@atdFilter.to_i==1)
		#result=Set.new(result.to_a.find_all{|a| a.done?}) if (@atdFilter.to_i==2)
	end
	print "benchmarking filterTasks", timetaken
	result
  end
  
    
  
  def filterRootActions(actions)
	result = nil
	timetaken=Benchmark.measure do
		if (@focus)
		  checkFocus
		  result=filterTasks(@focus)
		  result=result.to_a.sort_by {|x| x.sequencePath}
		else
		  result=Set.new(filterTasks(actions).collect { |task| task.rootAction})
		  result=result.to_a.sort_by {|x| x.sequencePath }
		end
	end
	print "benchmarking filterRootActions", timetaken
    result
  end
  
  def startingTasks
    sTasks=nil
    if @focus
      checkFocus
      sTasks=[]
      @focus.each{|a| a.selfPlusChildren(sTasks)}
    else
		timetaken=Benchmark.measure do
			sTasks=managedObjectContext.objectsForEntityNamed('Action')
		end
		print "benchmarking startingTasks", timetaken
    end
    sTasks
  end
  def tasks
    return @tasks.to_a if @tasks != nil
    @tasks=filterTasks(startingTasks)
    #result=$managedObjectContext.objectsForEntityNamed('Action')
    @tasks += @newlyCreated
    @tasks.to_a.sort_by {|x| x.sequencePath.to_i}
  end
  def rootActions
    return @rootActions if @rootActions != nil
    return @focus if @focus != nil
    @rootActions=filterRootActions(tasks)
    @rootActions
  end
  
  def rootObjects
    #print "rootObjects pulled\n"
    result = rootActions
    #print result.size," root actions\n"
    rootActions
  end
  
  def splitView_didCollapse(splitView,subView)
    subView.setHidden(true)
  end
  
  def taskSortDescriptors
    if @taskSortDescriptors ==nil
      @taskSortDescriptors=[ NSSortDescriptor.alloc.initWithKey_ascending("context.name",true),
          NSSortDescriptor.alloc.initWithKey_ascending("sequencePath",true),
          NSSortDescriptor.alloc.initWithKey_ascending("priority",true) ]
    end
    @taskSortDescriptors
  end
  
  def outlineSortDescriptors
    if @outlineSortDescriptors == nil
      @outlineSortDescriptors=[NSSortDescriptor.alloc.initWithKey_ascending("sequencePath",true)]
    end
    @outlineSortDescriptors
  end
  
  def outlineSortDescriptors=(value)
    #willChangeValueForKey "outlineSortDescriptors"
    #@outlineSortDescriptors=value
    #didChangeValueForKey "outlineSortDescriptors"
    print "osd written back\n"
  end
  
  def taskSortDescriptors=(value)
    willChangeValueForKey "taskSortDescriptors"
    @taskSortDescriptors=value
    didChangeValueForKey "taskSortDescriptors"
  end
  
  def contextNameSorter
    @contextNameSorter=[  NSSortDescriptor.alloc.initWithKey_ascending("name",true)] unless @contextNameSorter
    @contextNameSorter
 	end
 	
  def projectNameSorter
    @projectNameSorter=[NSSortDescriptor.alloc.initWithKey_ascending("isArea",false),
      NSSortDescriptor.alloc.initWithKey_ascending("name",true)] unless @projectNameSorter
    @projectNameSorter
 	end
 	
 	#def outlineView_willDisplayCell_forTableColumn_tableColumn_item(ov,cell,col,item)
 	#  @outlineController.outlineView_willDisplayCell_forTableColumn_item(ov,cel,col,item) if @outlineController != nil
  #end
  
  def tableViewSelectionDidChange(notif)
    if (!@selectionNotification)
	  @addOutline=false
      @selectionNotification=true
      taskController.selectedObjects.each {|a| scrollOutlineToAction(a); break } #scroll to first on the list
      outlineController.setSelectedObjects(taskController.selectedObjects)
      @selectionNotification=false
    end
  end
  
  def outlineViewSelectionIsChanging(notif)
    #if (notif.object == outlineView || notif.object.__ocid__ == outlineView.__ocid__) && !@selectionNotification
    if (notif.object == outlineView ) && !@selectionNotification
	  @addOutline=true
      @selectionNotification=true
        outlineController.selectedObjects.each {|a| scrollTaskToAction(a); break } #scroll to first on the list
        taskController.setSelectedObjects(outlineController.selectedObjects)
      @selectionNotification=false
    end
  end

  def validateMenuItem?(anItem)
    print "validating #{anItem.action}\n"
  	if anItem.action == :delete
  		return outlineController.selectedObjects.count > 0;
  	else
  		return super_validateMenuItem(anItem);
    end
  end
  
  def delete(sender)
    objToDelete=outlineController.selectedObjects
    outlineController.setSelectedObjects(nil)
    taskController.setSelectedObjects(nil)
    moc = $managedObjectContext
    objToDelete.each {|a| @newlyCreated.delete(a) }
	objToDelete=objToDelete.to_a
	#remove any children from selection
	objToDelete=objToDelete.reject{|a| objToDelete.any?{|a2| a != a2 && a.hasAncestor?(a2)}}
	parent = objToDelete[0].parent if objToDelete.size > 0
    objToDelete.each do |a| 
		moc.deleteObject(a) # should cascade delete
	end
	moc.processPendingChanges
    reset_visible_actions
	scrollToAction(parent) if parent
  end
  
  def tableView_writeRowsWithIndexes_toPasteboard(view,rows,pboard)
    taskController.setSelectionIndexes(rows)
    @@dragCopy=taskController.selectedObjects
    data=NSKeyedArchiver.archivedDataWithRootObject(@@dragCopy.valueForKeyPath("uniqueID"))
    return true
  end
  
  def tableView_acceptDrop_row_dropOperation(view,info,row,op)
    index=999
    case op
    when NSTableViewDropAbove
      if row==view.numberOfRows
#        if view.numberOfRows
#          newParent=taskController.arrangedObjects.objectAtIndex(row-1).parent
#        end
      elsif row==0
        index=0
#        newParent=nil
      else
        below=taskController.arrangedObjects.objectAtIndex(row-1)
        above=taskController.arrangedObjects.objectAtIndex(row)
#        newParent=above.parent
#        newParent=below.parent if (above.parent != below.parent)
        index=above.sequenceValue.to_i
      end
      @@dragCopy.each do |a| 
        a.setParentAtIndex(a.parent,index)
        index += 1
      end
    else
      newParent=taskController.arrangedObjects.objectAtIndex(row)
      @@dragCopy.each do |a| 
        if (!newParent || !newParent.hasAncestor?(a) || newParent==a.parent) 
          a.setParentAtIndex(newParent,index)
          a.setParentAtIndex(a.parent,index)
          index += 1
        end
      end
    end
    @@dragCopy.each do |a|
      if a.parent
        a.parent.resequence
      end
    end
    resequence
    return true
  end
  
  def removeChildrenFromSelection(selection)
	#remove children from selection so we don't do operations twice 
	selection2=selection.reject{|a| selection.any?{|a2| a != a2 && a.hasAncestor?(a2)}}
	selection2
  end

  
  def outlineView_writeItems_toPasteboard(view,items,pboard)
    data=NSKeyedArchiver.archivedDataWithRootObject(items.valueForKeyPath("representedObject.uniqueID"))
    @@dragCopy=items.valueForKeyPath("representedObject")
    @outlineController.setSelectedObjects(@@dragCopy)
	#remove children of dragged objects from copy because moving a parent moves the children by implication
	# but we don't want to adjust the parents of the children
	@@dragCopy=@@dragCopy.reject{|a| @@dragCopy.any?{|a2| a != a2 && a.hasAncestor?(a2)}}
    pboard.declareTypes_owner(@@dragTypes,self)
    pboard.setData_forType(data,@@dragTypes[0])
    return true
  end
  
  def tableView_validateDrop_proposedRow_proposedDropOperation(view,info,row,op)
    newParent=nil
    result=NSDragOperationGeneric
    case op
    when NSTableViewDropAbove
#      if row==view.numberOfRows
#        if view.numberOfRows
#          newParent=taskController.arrangedObjects.objectAtIndex(row).parent
#        end
#      elsif row<2
#        newParent=nil
#      else
#        below=taskController.arrangedObjects.objectAtIndex(row-1)
#        above=taskController.arrangedObjects.objectAtIndex(row)
#        newParent=above.parent
#        newParent=below.parent if (above.parent != below.parent)
#      end
    else
      newParent=taskController.arrangedObjects.objectAtIndex(row)
    end
    @@dragCopy.each do |a| 
      if (newParent && newParent.hasAncestor?(a) && newParent!=a.parent) 
        result=NSDragOperationNone
      end
    end
    return result
  end

  def outlineView_validateDrop_proposedItem_proposedChildIndex(view,info,item,index)
    return NSDragOperationGeneric if item == nil
    newParent=item.representedObject
    result=NSDragOperationGeneric
    @@dragCopy.each{|a| result=NSDragOperationNone if newParent.hasAncestor?(a) }
    result
  end
  
  def resequence
    roots=Set.new(managedObjectContext.objectsForEntityNamed('Action').collect { |task| task.rootAction})
    roots.to_a.sort_by {|x| x.sequencePath }
    roots.each_with_index {|a,i| a.setSequenceValue(i)}
    roots
  end
  
  def bumpRootsFromIndex_throughIndex(fromIndex,toIndex)
    bump= toIndex-fromIndex+1
    list= resequence
    list.each{|a| a.sequenceValue= a.sequenceValue.to_i+bump if a.sequenceValue.to_i >=fromIndex && a.sequenceValue.to_i <= toIndex }
  end
  
  def outlineView_acceptDrop_item_childIndex(view,info,item,index)
    newParent= item ? item.representedObject : nil
    index=index+1 #our indexes start at 1
    if !newParent
       bumpRootsFromIndex_throughIndex(index,index+@@dragCopy.count)
    end
    print "New Parent: #{newParent.name} New Index: #{index}\n"
    @@dragCopy.each do |a| 
      if (!newParent || !newParent.hasAncestor?(a) || newParent==a.parent) 
        a.setParentAtIndex(newParent,index)
        index += 1
      end
    end
    if newParent
      newParent.reset_kids
      newParent.resequence
    end
    resequence if !newParent
    @@dragCopy.each do |a|
      print "Final: New Parent: #{a.parent.name} New Index: #{a.sequenceValue}\n"
    end
    return true
  end
  def outlineView_didFinishDragOperation(view,operation)
    @@dragCopy=nil
  end
  def tableView_didFinishDragOperation(view,operation)
    @@dragCopy=nil
  end
  
  def newSchedulerWindow(sender)
    Scheduler.alloc.initWithActions(@outlineController.selectedObjects) if @outlineController.selectedObjects.count
  end
  
  def newBrowserWindow(sender)
    @appDelegate.newBrowserWindow(sender)
  end
  
  @@txtIcon=NSImage.imageNamed("txt")
  @@notxtIcon=NSImage.imageNamed("notxt")

  def tableView_willDisplayCell_forTableColumn_row(tv,cell,column,row)
  	obj=@taskController.arrangedObjects.objectAtIndex(row)
  	#print "display hoook #{column.identifier.to_s}\n"
  	if column.identifier.to_s == "note"
  	  if obj.note?
  			cell.setImage(@@txtIcon)
  		else
  			cell.setImage(@@notxtIcon)
  		end
  	end
  end
  
  def outlineView_shouldCollapseItem?(ov,item)
    return true
  end
    
  def outlineView_shouldSelectItem?(ov,item)
    return true
  end
  
  #def outlineView_willDisplayOutlineCell_forTableColumn_item(ov,cell,column,item)
  #end
  #def outlineView_willDisplayCell_forTableColumn_item(ov,cell,column,item)
  #end
  
  def focusOnSelection(sender)
    nfocus=@outlineController.selectedObjects.to_a
    nfocus=nfocus.reject{|a| nfocus.any?{|a2| a != a2 && a.hasAncestor?(a2)}}
    nfocus=nfocus.sort_by {|x| x.sequencePath }
    nbw=@appDelegate.newFocusWindow(nfocus)
  end
  
  def checkFocus
    if @focus
      @focus.reject!{|a| @focus.any?{|a2| a != a2 && a.hasAncestor?(a2)}}
    end
  end
  
  def openNotes(sender)
    @outlineController.selectedObjects.each{ |a| a.openNoteReader }
  end
  
  def doToday(sender)
    date = NSCalendarDate.calendarDate
    @outlineController.selectedObjects.each{ |a| a.setDoDate(date) }
  end
  
  def doTomorrow(sender)
    date = NSCalendarDate.calendarDate.dateByAddingDays(1)
    @outlineController.selectedObjects.each{ |a| a.setDoDate(date) }
  end
  
  def setDoDateByDayOfWeek(dow)
    date=NSCalendarDate.calendarDate
    today=date.dayOfWeek
    dow=0 if dow==7
    dow=7 if dow==14
    dow=dow-today
    @outlineController.selectedObjects.takeValue_forKey(date.dateByAddingDays(dow),"doDateDate")
  end
  def doMonday(sender)
    setDoDateByDayOfWeek(1)
  end
  def doTuesday(sender)
    setDoDateByDayOfWeek(2)
  end
  def doWednesday(sender)
    setDoDateByDayOfWeek(3)
  end
  def doThursday(sender)
    setDoDateByDayOfWeek(4)
  end
  def doFriday(sender)
    setDoDateByDayOfWeek(5)
  end
  def doSaturday(sender)
    setDoDateByDayOfWeek(6)
  end
  def doSunday(sender)
    setDoDateByDayOfWeek(7)
  end
  
  def doNextMonday(sender)
    setDoDateByDayOfWeek(1+7)
  end
  def doNextTuesday(sender)
    setDoDateByDayOfWeek(2+7)
  end
  def doNextWednesday(sender)
    setDoDateByDayOfWeek(3+7)
  end
  def doNextThursday(sender)
    setDoDateByDayOfWeek(4+7)
  end
  def doNextFriday(sender)
    setDoDateByDayOfWeek(5+7)
  end
  def doNextSaturday(sender)
    setDoDateByDayOfWeek(6+7)
  end
  def doNextSunday(sender)
    setDoDateByDayOfWeek(7+7)
  end
  
  def startAction(sender)
    date = NSCalendarDate.calendarDate
    @outlineController.selectedObjects.each{ |a| a.setStartDate(date) }
  end
  
  def finishAction(sender)
    date = NSCalendarDate.calendarDate
    @outlineController.selectedObjects.each{ |a| a.setDone(1); a.setFinishDate(date) }
  end
  
  def actionImportant(sender)
    value=1
    value=0 if @outlineController.selectedObjects.all? {|a| a.isImportant?}
    @outlineController.selectedObjects.each{ |a| a.setIsImportant(value) }
  end
  
  def actionUrgent(sender)
    value=1
    value=0 if @outlineController.selectedObjects.all? {|a| a.isUrgent?}
    @outlineController.selectedObjects.each{ |a| a.setIsUrgent(value) }
  end
  
  def actionParallel(sender)
    value=0
    @outlineController.selectedObjects.each{ |a| a.setIsSequential(value) }
  end
   def actionSequential(sender)
    value=1
    @outlineController.selectedObjects.each{ |a| a.setIsSequential(value) }
  end
   def actionSomeday(sender)
    value=1
    value=0 if @outlineController.selectedObjects.all? {|a| a.isSomedayUp?}
    @outlineController.selectedObjects.each{ |a| a.setIsSomeday(value) }
  end
  
  def actionArea(sender)
    value=1
    value=0 if @outlineController.selectedObjects.all? {|a| a.isArea?}
    @outlineController.selectedObjects.each{ |a| a.setIsArea(value) }
  end
  
  def actionTemplate(sender)
    value=1
    value=0 if @outlineController.selectedObjects.all? {|a| a.isTemplateUp?}
    @outlineController.selectedObjects.each{ |a| a.setIsTemplate(value) }
  end
  
  def buildTemplate(sender)
	tParents= Set.new
	@outlineController.selectedObjects.each do  |a|
		tParents << a.templateParent
	end
	newTasks=[]
	tParents.each do |a|
		newA=a.instantiateTemplate
		newA.selfPlusChildren(newTasks)
	end
	@newlyCreated += newTasks
	reset_visible_actions
  end
  
  def print_ToDoA(sender)
    @printer=TemplatePrinter.alloc.init
	@printer.printTasksWithTemplate(@taskController.arrangedObjects,ToDoTemplate_A.new)
  end
  
  def printOutline(sender)
	template= OutlineHTML.new
	html= template.buildHTMLForProjects(rootActions(),self)
	newPrintWindow(html)
    #@printer=TemplatePrinter.alloc.init
	#@printer.printHTML(html)
  end

  def newPrintWindow(html)
	hw=PrintWindow.alloc.init
	hw.setupWithHTML(self,html)
	hw
  end
  
  def tableViewDefaultColumnIdentifiers(tableview)
    print "tableViewDefaultColumnIdentifiers called\n"
    return ["done","note","name","context","project","important","urgent","startDate","doDate","dueDate"]
  end
  #objc_method :tableViewDefaultColumnIdentifiers,%w{id}
  
  def tableViewTypeAheadSelectionColumn(tableview)
    print "tableViewTypeAheadSelectionColumn id called\n"
    tableview.columnWithIdentifier("name")
  end
  #objc_method :tableViewTypeAheadSelectionColumn,%w{id id}
  def tableViewColumnIdentifiersForDragImage(tableview)
    print "tableViewColumnIdentifiersForDragImage called\n"
    return ["name"]
  end
  #objc_method :tableViewColumnIdentifiersForDragImage,%w{id id}
  
  def configurableColumnTableView_menuStringForColumn(tableView,column)
    return @@columnNames[column.identifier.to_s]
  end
  def configurableColumnOutlineView_menuStringForColumn(ov,column)
    configurableColumnTableView_menuStringForColumn(ov,column)
  end
  #objc_method :configureableColumnTableView_menuStringForColumn,%w{id id id}
  
  def configurableColumnTableView_shouldAllowTogglingColumn(tv,column)
    which=column.identifier
    case which.to_s
    when "name"
      return nil
    when "done"
      return nil
    else    
      return 1
    end
  end
  def configurableColumnOutlineView_shouldAllowTogglingColumn(ov,column)
    configurableColumnTableView_shouldAllowTogglingColumn(ov,column)
  end
  #objc_method :configurableColumnTableView_shouldAllowTogglingColumn,%w{bool id id}
  
  def nameForRow(row)
    return @taskController.arrangedObjects.objectAtIndex(row).valueForKey("name")
  end
  
#  def tableView_objectValueForTableColumn_row(tv,column,row)
#    print "obj Value #{column.identifier} #{@@columnPaths[column.identifier.to_s]}\n"
#    return @taskController.arrangedObjects.objectAtIndex(row).valueForKeyPath(@@columnPaths[column.identifier.to_s])
#  end

 def outlineView_willDisplayCell_forTableColumn_item(ov,cell,column,item)
  # print "outlineView_willDisplayCell_forTableColumn_item",ov,@filterView,(ov == @filterView),"\n"
  # print "ids",ov.object_id,@filterView.object_id,(ov.object_id == @filterView.object_id),"\n"
  # print "ocids",ov.__ocid__,@filterView.__ocid__,(ov.__ocid__ == @filterView.__ocid__),"\n"
   case ov.__ocid__
   when @filterView.__ocid__
     cell.setTitle(item.representedObject.name)
     cell.setState(item.representedObject.selected)
   else
   end
 end

 def viewsClick(sender)
	which = sender.selectedSegment
	case which
	when 0
		splitViewV.subviewAtPosition(0).toggleCollapse(sender)
	when 1
		splitViewH.subviewAtPosition(0).toggleCollapse(sender)
	when 2
		splitViewH.subviewAtPosition(1).toggleCollapse(sender)
	end
 end
  
 def setDelegateTo_returnCode_context(picker,returncode,context)
	case returncode
	when 1
		sel=outlineController.selectedObjects
		sel=removeChildrenFromSelection(sel)
		choice=pickerPicker.selectedRecords[0]
		@emailText="" if @emailText=="Enter any extra text for the email here"
		sel.each do |a|
			a.doDelegateTo(choice,pickerPicker.selectedValues[0],@emailText)
		end
	when -1 
		sel=outlineController.selectedObjects
		sel.each do |a|
			a.delegatedToID=nil
		end
	end
		
	return true
 end
 
  def setDelegateFrom_returnCode_context(picker,returncode,context)
	case returncode
	when 1
		sel=outlineController.selectedObjects
		choice=pickerPicker.selectedRecords[0]
		sel.each do |a|
			a.delegatedFromID=choice.uniqueId
		end
	when -1 
		sel=outlineController.selectedObjects
		sel.each do |a|
			a.delegatedFromID=nil
		end
	end
		
	return true
 end
 
 def personChose(sender)
    pickerView.endEditingFor(nil)
	NSApplication.sharedApplication.endSheet_returnCode(pickerView,1)
	pickerView.close
	return true
 end
 
 def personCancel(sender)
	print "got cancel"
	NSApplication.sharedApplication.endSheet_returnCode(pickerView,0)
	pickerView.close
	return true
 end
 
 def personClear(sender)
	NSApplication.sharedApplication.endSheet_returnCode(pickerView,-1)
	pickerView.close
	return true
 end
 
 def delegateItemsTo(sender)
    @pickerLabel="Select the person to delegate to:"
	@emailText=""
	result=NSBundle.loadNibNamed_owner("ABPicker",self)
	pickerPicker.setNameDoubleAction('personChose:')
	pickerPicker.setTarget(self)
	if (outlineController.selectedObjects && outlineController.selectedObjects.length > 0)
		abperson=nil
		sel=outlineController.selectedObjects[0]
		abperson= sel.delegatedTo if sel.delegatedToID?
		pickerPicker.selectRecord_byExtendingSelection(abperson,false) if abperson
	end
	NSApplication.sharedApplication.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(pickerView,browserWindow,self,'setDelegateTo:returnCode:context:',nil)
	
 end

 def delegateItemsFrom(sender)
    @pickerLabel="Select the person to delegate from:"
	result=NSBundle.loadNibNamed_owner("ABPicker",self)
	pickerPicker.setNameDoubleAction('personChose:')
	pickerPicker.setTarget(self)
	if (outlineController.selectedObjects && outlineController.selectedObjects.length > 0)
		abperson=nil
		sel=outlineController.selectedObjects[0]
		abperson= sel.delegatedFrom if sel.delegatedFromID?
		pickerPicker.selectRecord_byExtendingSelection(abperson,false) if abperson
	end
	NSApplication.sharedApplication.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(pickerView,browserWindow,self,'setDelegateFrom:returnCode:context:',nil)
 end
 
   def doDefer_returnCode_context(picker,returncode,context)
	case returncode
	when 1
		sel=outlineController.selectedObjects
		sel.each do |a|
			a.startDate=deferDate
		end
	end
   end

	def processQuickSplit(newEntry,parent)
	  print "Quick Split: #{newEntry}\n"
	  return if !newEntry || newEntry.length==0
	  newAction=createActionWithParentAtIndex(parent,0)
	  #newAction.setParent(parent)
	  newAction.smartName= newEntry
	  newAction.setContext(newAction.parent.context()) if (newAction.parent? && !newAction.context? && newAction.parent.context?)
	  $managedObjectContext.processPendingChanges
	  newAction
	end

   def doQuickSplit_returnCode_context(picker,returncode,context)
     undoManager.endUndoGrouping
	 undoManager.setActionName("Quick Split")
     case returncode
	 when 1
		 parent=outlineController.selectedObjects[0]
		 list=[]
		 quickSplitText.split("\n").each{ |s| list << processQuickSplit(s,parent) }
		 @outlineController.setSelectedObjects(list)
		 @taskController.setSelectedObjects(list)	  
		 scrollToAction(list[0]) if list[0]
	 end
   end
   
 
 def deferCancel(sender)
	NSApplication.sharedApplication.endSheet_returnCode(deferView,-1)
	deferView.close
	return true
 end
 
 def deferDone(sender)
	NSApplication.sharedApplication.endSheet_returnCode(deferView,1)
	deferView.close
	return true
 end
 
 def quickSplitDone(sender)
    quickSplitView.endEditingFor(nil)
 	NSApplication.sharedApplication.endSheet_returnCode(quickSplitView,1)
	quickSplitView.close
	return true
 end
 def quickSplitCancel(sender)
 	NSApplication.sharedApplication.endSheet_returnCode(quickSplitView,-1)
	quickSplitView.close
	return true
 end

 def hasSelection?
		if (outlineController.selectedObjects && outlineController.selectedObjects.length > 0)
			return true
		end
		false
 end
  
 def deferItems(sender)
    return unless hasSelection?
	@deferDate=NSCalendarDate.date
	result=NSBundle.loadNibNamed_owner('Defer',self)
	NSApplication.sharedApplication.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(deferView,browserWindow,self,'doDefer:returnCode:context:',nil)	
 end

 def quickSplit(sender)
    return unless hasSelection?
	if (outlineController.selectedObjects && outlineController.selectedObjects.length == 1)
		sel=outlineController.selectedObjects[0]
		@splitLabel = "QuickSplitting: #{sel.name}"
		@quickSplitText=""
	end
	undoManager.beginUndoGrouping
	result=NSBundle.loadNibNamed_owner('QuickSplit',self)
	NSApplication.sharedApplication.beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo(quickSplitView,browserWindow,self,'doQuickSplit:returnCode:context:',nil)	
 end
 
 def windowWillReturnUndoManager(window)
	return undoManager
 end
 
 def undoManager
	return managedObjectContext.undoManager
 end
  
end