// This method is called from TreeView and handles: // - Where the dragged items are dropped (above, below or upon) // - Auto expansion of collapsed items when hovering over them // - Setting up the render markers for drop location (horizontal lines) // 'targetItem' is null when not hovering over any target Item, if so the rest of the arguments are invalid public virtual bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row) { bool perform = Event.current.type == EventType.DragPerform; // Are we dragging outside any items if (targetItem == null) { // If so clear any drop markers if (m_DropData != null) { m_DropData.dropTargetControlID = 0; m_DropData.rowMarkerControlID = 0; } // And let client decide what happens when dragging outside items DragAndDrop.visualMode = DoDrag(null, null, perform, DropPosition.Below); if (DragAndDrop.visualMode != DragAndDropVisualMode.None && perform) { FinalizeDragPerformed(true); } return(false); } DropPosition dropPosition; if (!TryGetDropPosition(targetItem, targetItemRect, row, out dropPosition)) { return(false); } TreeViewItem parentItem = null; switch (dropPosition) { case DropPosition.Upon: { // Client must decide what happens when dropping upon: e.g: insert last or first in child list parentItem = targetItem; } break; case DropPosition.Below: { // When hovering between an expanded parent and its first child then make sure we change state to match that if (m_TreeView.data.IsExpanded(targetItem) && targetItem.hasChildren) { parentItem = targetItem; targetItem = targetItem.children[0]; dropPosition = DropPosition.Above; } else { // Drop as next sibling to target parentItem = targetItem.parent; } } break; case DropPosition.Above: { parentItem = targetItem.parent; } break; default: Assert.IsTrue(false, Constants.UnhandledEnum); break; } DragAndDropVisualMode mode = DragAndDropVisualMode.None; if (perform) { // Try Drop on top of element if (dropPosition == DropPosition.Upon) { mode = DoDrag(targetItem, targetItem, true, dropPosition); } // Fall back to dropping on parent (drop between elements) if (mode == DragAndDropVisualMode.None && parentItem != null) { mode = DoDrag(parentItem, targetItem, true, dropPosition); } // Finalize drop if (mode != DragAndDropVisualMode.None) { FinalizeDragPerformed(false); } else { DragCleanup(true); m_TreeView.NotifyListenersThatDragEnded(null, false); } } else // DragUpdate { if (m_DropData == null) { m_DropData = new DropData(); } m_DropData.dropTargetControlID = 0; m_DropData.rowMarkerControlID = 0; int itemControlID = TreeViewController.GetItemControlID(targetItem); HandleAutoExpansion(itemControlID, targetItem, targetItemRect); // Try drop on top of element if (dropPosition == DropPosition.Upon) { mode = DoDrag(targetItem, targetItem, false, dropPosition); } if (mode != DragAndDropVisualMode.None) { m_DropData.dropTargetControlID = itemControlID; DragAndDrop.visualMode = mode; } // Fall back to dropping on parent (drop between elements) else if (targetItem != null && parentItem != null) { mode = DoDrag(parentItem, targetItem, false, dropPosition); if (mode != DragAndDropVisualMode.None) { drawRowMarkerAbove = dropPosition == DropPosition.Above; m_DropData.rowMarkerControlID = itemControlID; DragAndDrop.visualMode = mode; } } } Event.current.Use(); return(true); }
// This method is called from TreeView and handles: // - Where the dragged items are dropped (above, below or upon) // - Auto expansion of collapsed items when hovering over them // - Setting up the render markers for drop location (horizontal lines) // 'targetItem' is null when not hovering over any target Item, if so the rest of the arguments are invalid public virtual bool DragElement(TreeViewItem targetItem, Rect targetItemRect, int row) { bool perform = Event.current.type == EventType.DragPerform; // Are we dragging outside any items if (targetItem == null) { // If so clear any drop markers if (m_DropData != null) { m_DropData.ClearPerEventState(); } // And let client decide what happens when dragging outside items DragAndDrop.visualMode = DoDrag(null, null, perform, DropPosition.Below); if (DragAndDrop.visualMode != DragAndDropVisualMode.None && perform) { FinalizeDragPerformed(true); } return(false); } DropPosition dropPosition; if (!TryGetDropPosition(targetItem, targetItemRect, row, out dropPosition)) { return(false); } TreeViewItem parentItem = null; TreeViewItem dropRelativeToItem = targetItem; bool didChangeTargetToAncector = false; DropPosition originalDropPosition = dropPosition; switch (dropPosition) { case DropPosition.Upon: // Parent change: Client must decide what happens when dropping upon: e.g: insert last or first in child list parentItem = dropRelativeToItem; break; case DropPosition.Below: case DropPosition.Above: // Sibling change if (getIndentLevelForMouseCursor != null) { int cursorDepth = getIndentLevelForMouseCursor(); HandleSiblingInsertionAtAvailableDepthsAndChangeTargetIfNeeded(ref dropRelativeToItem, row, ref dropPosition, cursorDepth, out didChangeTargetToAncector); } else { if (dropPosition == DropPosition.Below && m_TreeView.data.IsExpanded(dropRelativeToItem) && dropRelativeToItem.hasChildren) { // When hovering between an expanded parent and its first child then make sure we change state to match that dropPosition = DropPosition.Above; dropRelativeToItem = dropRelativeToItem.children[0]; } } parentItem = dropRelativeToItem.parent; break; default: Debug.LogError("Unhandled enum. Report a bug."); break; } if (perform) { DragAndDropVisualMode mode = DragAndDropVisualMode.None; // Try Drop upon target item if (dropPosition == DropPosition.Upon) { mode = DoDrag(dropRelativeToItem, dropRelativeToItem, true, dropPosition); } // Drop between items if (mode == DragAndDropVisualMode.None && parentItem != null) { mode = DoDrag(parentItem, dropRelativeToItem, true, dropPosition); } // Finalize drop if (mode != DragAndDropVisualMode.None) { FinalizeDragPerformed(false); } else { DragCleanup(true); m_TreeView.NotifyListenersThatDragEnded(null, false); } } else // DragUpdate { if (m_DropData == null) { m_DropData = new DropData(); } m_DropData.ClearPerEventState(); // Try drop on top of items if (dropPosition == DropPosition.Upon) { int itemControlID = TreeViewController.GetItemControlID(dropRelativeToItem); HandleAutoExpansion(itemControlID, dropRelativeToItem, targetItemRect); var mode = DoDrag(dropRelativeToItem, dropRelativeToItem, false, dropPosition); if (mode != DragAndDropVisualMode.None) { m_DropData.dropTargetControlID = itemControlID; DragAndDrop.visualMode = mode; } } // Drop between items else if (dropRelativeToItem != null && parentItem != null) { var mode = DoDrag(parentItem, dropRelativeToItem, false, dropPosition); if (mode != DragAndDropVisualMode.None) { drawRowMarkerAbove = dropPosition == DropPosition.Above; m_DropData.rowMarkerControlID = TreeViewController.GetItemControlID(dropRelativeToItem); m_DropData.insertionMarkerYPosition = originalDropPosition == DropPosition.Above ? targetItemRect.y : targetItemRect.yMax; m_DropData.insertRelativeToSibling = dropRelativeToItem; if (didChangeTargetToAncector) { m_DropData.ancestorControlID = TreeViewController.GetItemControlID(dropRelativeToItem); } DragAndDrop.visualMode = mode; } } } Event.current.Use(); return(true); }