Esempio n. 1
0
        private void treeviewDragVerifyHandler(object sender, DragVerifyEventArgs e)
        {
            // we need to go through all nodes that would be moved (source nodes), and check if there's any
            // problem moving any of them to the target node (circular references, etc.), since it's possible
            // for a element to exist multiple times in the treeview as different treenodes.

            List <ElementNode> nodes = new List <ElementNode>(e.SourceNodes.Select(x => x.Tag as ElementNode));

            // now get a list of invalid children for this target node, and check all the remaining nodes against it.
            // If any of them fail, the entire operation should fail, as it would be an invalid move.

            // the target node will be the actual target node if it is directly on it, otherwise it would be the parent
            // of the target node if it would be dragged above/below the taget element (as it would be put alongside it).
            // also keep track of the 'permitted' nodes: this is used when dragging alongside another element: any children
            // of the new parent node are considered OK, as we might just be shuffling them around. Normally, this would
            // be A Bad Thing, since it would seem like we're adding a child to the group it's already in. (This is only
            // the case when moving; if copying, it should be disabled. That's checked later.)
            IEnumerable <ElementNode> invalidNodesForTarget   = null;
            IEnumerable <ElementNode> permittedNodesForTarget = null;

            if (e.DragBetweenNodes == DragBetweenNodes.DragOnTargetNode ||
                e.DragBetweenNodes == DragBetweenNodes.DragBelowTargetNode && e.TargetNode.IsExpanded)
            {
                invalidNodesForTarget   = (e.TargetNode.Tag as ElementNode).InvalidChildren();
                permittedNodesForTarget = new HashSet <ElementNode>();
            }
            else
            {
                if (e.TargetNode.Parent == null)
                {
                    invalidNodesForTarget   = VixenSystem.Nodes.InvalidRootNodes;
                    permittedNodesForTarget = VixenSystem.Nodes.GetRootNodes();
                }
                else
                {
                    invalidNodesForTarget   = (e.TargetNode.Parent.Tag as ElementNode).InvalidChildren();
                    permittedNodesForTarget = (e.TargetNode.Parent.Tag as ElementNode).Children;
                }
            }

            if ((e.KeyState & 8) != 0)
            {
                // the CTRL key
                e.DragMode = DragDropEffects.Copy;
                permittedNodesForTarget = new HashSet <ElementNode>();
            }
            else
            {
                e.DragMode = DragDropEffects.Move;
            }

            IEnumerable <ElementNode> invalidSourceNodes = invalidNodesForTarget.Intersect(nodes);

            if (invalidSourceNodes.Any())
            {
                if (invalidSourceNodes.Intersect(permittedNodesForTarget).Count() == invalidSourceNodes.Count())
                {
                    e.ValidDragTarget = true;
                }
                else
                {
                    e.ValidDragTarget = false;
                }
            }
            else
            {
                e.ValidDragTarget = true;
            }
        }
Esempio n. 2
0
        protected override void OnDragOver(DragEventArgs e)
        {
            // Change any previous node back
            if (_dragDestinationNode != null)
            {
                DrawNodeAsNormal(_dragDestinationNode);
            }

            // Get the node from the mouse position, colour it
            Point pt = PointToClient(new Point(e.X, e.Y));

            _dragDestinationNode = GetNodeAt(pt);

            if (_dragDestinationNode != null)
            {
                // try and figure out if we would be dragging 'between' nodes.
                if (_dragDestinationNode.Bounds.Contains(pt) && pt.Y - _dragDestinationNode.Bounds.Top <= 3)
                {
                    _dragBetweenState = DragBetweenNodes.DragAboveTargetNode;
                }
                else if (_dragDestinationNode.Bounds.Contains(pt) && _dragDestinationNode.Bounds.Bottom - pt.Y <= 3)
                {
                    _dragBetweenState = DragBetweenNodes.DragBelowTargetNode;
                }
                else
                {
                    _dragBetweenState = DragBetweenNodes.DragOnTargetNode;
                }

                // figure out where to draw the dotted line to show where it would be moving to.
                if (DraggingBetweenRows)
                {
                    if (_dragBetweenState == DragBetweenNodes.DragAboveTargetNode)
                    {
                        _dragBetweenRowsDrawLineStart = new Point(_dragDestinationNode.Bounds.Left, _dragDestinationNode.Bounds.Top);
                        _dragBetweenRowsDrawLineEnd   = new Point(_dragDestinationNode.Bounds.Right + 10, _dragDestinationNode.Bounds.Top);
                    }
                    else if (_dragBetweenState == DragBetweenNodes.DragBelowTargetNode)
                    {
                        _dragBetweenRowsDrawLineStart = new Point(_dragDestinationNode.Bounds.Left, _dragDestinationNode.Bounds.Bottom);
                        _dragBetweenRowsDrawLineEnd   = new Point(_dragDestinationNode.Bounds.Right + 10, _dragDestinationNode.Bounds.Bottom);
                    }
                    else
                    {
                        _dragBetweenRowsDrawLineStart = new Point(-1, -1);
                        _dragBetweenRowsDrawLineEnd   = new Point(-1, -1);
                    }

                    if (_dragLastLineDrawnY != _dragBetweenRowsDrawLineStart.Y)
                    {
                        Invalidate();
                        _dragLastLineDrawnY = _dragBetweenRowsDrawLineStart.Y;
                    }
                }
            }
            else
            {
            }

            // get the nodes that are being dragged from the drag data
            List <TreeNode> dragNodes = null;

            if (e.Data.GetDataPresent(typeof(List <TreeNode>)))
            {
                dragNodes = (List <TreeNode>)e.Data.GetData(typeof(List <TreeNode>));
            }

            if (dragNodes != null)
            {
                // if the target node is in the dragged nodes, it's not a valid point: don't select it
                if (_dragDestinationNode != null && dragNodes.Contains(_dragDestinationNode))
                {
                    _dragDestinationNode = null;
                }
            }

            if (dragNodes != null && _dragDestinationNode != null)
            {
                // if there's been a verification call setup, call it to check that the
                // target node is OK. otherwise, assume it is.
                if (DragOverVerify != null)
                {
                    DragVerifyEventArgs ea = new DragVerifyEventArgs();
                    ea.SourceNodes      = dragNodes;
                    ea.TargetNode       = _dragDestinationNode;
                    ea.DragBetweenNodes = _dragBetweenState;
                    ea.KeyState         = e.KeyState;
                    ea.DragMode         = _dragDefaultMode;
                    DragOverVerify(this, ea);

                    if (ea.ValidDragTarget)
                    {
                        e.Effect = ea.DragMode;
                    }
                    else
                    {
                        e.Effect             = DragDropEffects.None;
                        _dragDestinationNode = null;
                    }
                }
                else
                {
                    e.Effect = _dragDefaultMode;
                }

                if (_dragDestinationNode != null && !DraggingBetweenRows)
                {
                    DrawNodeAsDragDestination(_dragDestinationNode);
                }
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

            // Scrolling down/up
            if (pt.Y + 10 > ClientSize.Height)
            {
                SendMessage(Handle, 277, (IntPtr)1, 0);
            }
            else if (pt.Y < Top + 10)
            {
                SendMessage(Handle, 277, (IntPtr)0, 0);
            }
        }