// 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);
        }
示例#2
0
        // 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);
        }