Skip to content

Instantly share code, notes, and snippets.

@BlairDuncan
Created August 6, 2011 14:47
Show Gist options
  • Save BlairDuncan/1129399 to your computer and use it in GitHub Desktop.
Save BlairDuncan/1129399 to your computer and use it in GitHub Desktop.
- (CPDragOperation)outlineView:(CPOutlineView)theOutlineView validateDrop:(id)info proposedItem:(id)item proposedChildIndex:(CPInteger)childIndex
{
if(CPLOG_ON) CPLog.debug(self + _cmd + item + " proposedChildIndex:" + childIndex);
// This method validates whether or not the proposal is a valid one.
// We start out by assuming that we will do a "generic" drag operation, which means we are accepting the drop. If we return CPDragOperationNone, then we are not accepting the drop.
var result = CPDragOperationGeneric;
if ([self onlyAcceptDropOnRoot:info])
{
// We are going to accept the drop, but we want to retarget the drop item to be "on" the entire outlineView
[theOutlineView setDropItem:nil dropChildIndex:CPOutlineViewDropOnItemIndex];
}
else
{
// Check to see what we are proposed to be dropping on
var targetNode = item;
// A target of "nil" means we are on the main root tree
if (targetNode == nil)
targetNode = rootTreeNode;
var nodeData = [targetNode representedObject];
if (nodeData.container)
{
// See if we allow dropping "on" or "between"
if (childIndex == CPOutlineViewDropOnItemIndex)
{
if (![self allowOnDropOnContainer:nodeData info:info])// Refuse to drop on a container if we are not allowing that
result = CPDragOperationNone;
}
else
{
if (![self allowBetweenDrop:info]) // Refuse to drop between an item if we are not allowing that
result = CPDragOperationNone;
}
}
else
{
// The target node is not a container, but a leaf. See if we allow dropping on a leaf. If we don't, refuse the drop (we may get called again with a between)
if (childIndex == CPOutlineViewDropOnItemIndex && ![self allowOnDropOnLeaf:nodeData info:info])
result = CPDragOperationNone;
}
// If we are allowing the drop, we see if we are draggng from ourselves and dropping into a descendent, which wouldn't be allowed...
if (result != CPDragOperationNone)
{
if ([info draggingSource] == theOutlineView)
{
// Yup, the drag is originating from ourselves. See if the appropriate drag information is available on the pasteboard
if (targetNode != rootTreeNode && [[info draggingPasteboard] availableTypeFromArray:[CPArray arrayWithObject:SIMPLE_PBOARD_TYPE]] != nil)
{
var count = [draggedNodes count];
for (var i = 0; i < count; i++)
{
var draggedNode = [draggedNodes objectAtIndex:i];
if ([self treeNode:targetNode isDescendantOfNode:draggedNode])
{
// Yup, it is, refuse it.
result = CPDragOperationNone;
break;
}
}
}
}
}
}
// To see what we decide to return, uncomment this line
// if(CPLOG_ON) CPLog(result == CPDragOperationNone ? self + _cmd + @" - Refusing drop" : self + _cmd + @" + Accepting drop");
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment