/// <summary> /// Process the DragOver node in order to determine whether drop action as appropriate /// </summary> private void TreeViewEditor_DragOver(object sender, System.Windows.Forms.DragEventArgs e) { e.Effect = DragDropEffects.None; // By default, drag and drop is denied if (project == null) return; TreeView senderTreeView = sender as TreeView; if (senderTreeView != this) return; // Determine source and destination nodes Point pt = PointToClient(new Point(e.X, e.Y)); TreeNode dropNode = GetNodeAt(pt); if (dropNode == null) return; if (e.Data.GetDataPresent("System.Drawing.Design.ToolboxItem", false)) { ToolboxItem source = e.Data.GetData("System.Drawing.Design.ToolboxItem") as ToolboxItem; if (source != null && dropNode != null) { // Drop is available - highlight destination node this.SelectedNode = dropNode; if (project.IsChildElementAllowed(dropNode, source.TypeName)) { if (this.SelectedNode != null) this.SelectedNode.Expand(); e.Effect = DragDropEffects.Copy; } } //e.Effect = DragDropEffects.None; } // Fired continuously while a tree node is dragged. We need to override this to // provide appropriate feedback else if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false)) { TreeNode dragNode = e.Data.GetData("System.Windows.Forms.TreeNode") as TreeNode; if (dragNode == null) return; int OffsetY = pt.Y - dropNode.Bounds.Top; bool isList = project.IsList(dropNode); bool isGroup = project.IsGroup(dropNode); if (isList) // Adding a child is the only option for a list { if (IsDragAllowed(dragNode, dropNode, DropSide.Inside)) { e.Effect = DragDropEffects.Move; if (dropNode != prevDropNode || prevDropSide != DropSide.Inside) { prevDropNode = dropNode; prevDropSide = DropSide.Inside; DrawAddToFolderPlaceholder(dropNode); } } } else if (isGroup) // There are 3 options for a Group { if (OffsetY < (dropNode.Bounds.Height / 3)) // top third { if (IsDragAllowed(dragNode, dropNode, DropSide.Top)) { e.Effect = DragDropEffects.Move; if (prevDropNode != dropNode || prevDropSide != DropSide.Top) { prevDropNode = dropNode; prevDropSide = DropSide.Top; DrawLeafTopPlaceholders(dropNode); } } } // It is not allowed to drag a node just below an expanded Group node else if (OffsetY > (2 * dropNode.Bounds.Height / 3) && dropNode.IsExpanded == false) // bottom third { if (IsDragAllowed(dragNode, dropNode, DropSide.Bottom)) { e.Effect = DragDropEffects.Move; if (prevDropNode != dropNode || prevDropSide != DropSide.Bottom) { prevDropNode = dropNode; prevDropSide = DropSide.Bottom; DrawLeafBottomPlaceholders(dropNode); } } } else // middle => Add dragComp as a child { if (IsDragAllowed(dragNode, dropNode, DropSide.Inside)) { e.Effect = DragDropEffects.Move; if (dropNode != prevDropNode || prevDropSide != DropSide.Inside) { prevDropNode = dropNode; prevDropSide = DropSide.Inside; DrawAddToFolderPlaceholder(dropNode); } } } } else // 2 options for an ordinary component: Top or Bottom { if (IsDragAllowed(dragNode, dropNode, DropSide.Top)) { e.Effect = DragDropEffects.Move; if (OffsetY < (dropNode.Bounds.Height / 2)) // top half { if (prevDropNode != dropNode || prevDropSide != DropSide.Top) { prevDropNode = dropNode; prevDropSide = DropSide.Top; DrawLeafTopPlaceholders(dropNode); } } else // bottom half { if (prevDropNode != dropNode || prevDropSide != DropSide.Bottom) { prevDropNode = dropNode; prevDropSide = DropSide.Bottom; DrawLeafBottomPlaceholders(dropNode); } } } } if (e.Effect == DragDropEffects.None) { // Need to clear the drop markers, but only once to avoid flickering! if (prevDropNode != null) { prevDropNode = null; Refresh(); } } // Determine source and destination nodes // Point pt = senderTreeView.PointToClient(new Point(e.X, e.Y)); // TreeNode sourceTreeNode = e.Data.GetData("System.Windows.Forms.TreeNode") as TreeNode; // TreeNode destinationTreeNode = senderTreeView.GetNodeAt(pt); // // // Deny drag and drop when // // destinationNode is the same as source // // destination node is a parent of a source node // // destination and source node belong to the different TreeViews // if (sourceTreeNode == null || destinationTreeNode == null // || sourceTreeNode == destinationTreeNode // || (sourceTreeNode.Parent != null && sourceTreeNode.Parent == destinationTreeNode) // || sourceTreeNode.TreeView != destinationTreeNode.TreeView) // { // e.Effect = DragDropEffects.None; // return; // } // // // if destination node lies in a subtree of source node - restrict drop action to avoid circles // TreeNode checkParentNode = destinationTreeNode.Parent; // while (checkParentNode != null) // { // if (checkParentNode == sourceTreeNode) // { // e.Effect = DragDropEffects.None; // return; // } // checkParentNode = checkParentNode.Parent; // } // // // Drop is available - highlight destination node // this.SelectedNode = destinationTreeNode; // if (this.SelectedNode != null) // { // this.SelectedNode.Expand(); // } // // // determine a type of drug and drop action (move or copy) // if ((e.KeyState & 8) == 8) // { // // CTRL Keystate for copy // e.Effect = DragDropEffects.Copy; // } // else // { // e.Effect = DragDropEffects.Move; // } } //scrolling code int delta = Height - pt.Y; if ((delta < Height / 2) && (delta > 0)) { TreeNode tn = GetNodeAt(pt); if (tn.NextVisibleNode != null) tn.NextVisibleNode.EnsureVisible(); } if ((delta > Height / 2) && (delta < Height)) { TreeNode tn = GetNodeAt(pt); if (tn.PrevVisibleNode != null) tn.PrevVisibleNode.EnsureVisible(); } }
private bool IsDragAllowed(TreeNode dragNode, TreeNode dropNode, DropSide dropSide) { // Deny drag and drop when // destinationNode is the same as source // destination node is a parent of a source node // destination and source node belong to the different TreeViews if (dragNode == null || dropNode == null || dragNode == dropNode || (dragNode.Parent != null && dragNode.Parent == dropNode) || dragNode.TreeView != dropNode.TreeView) { return false; } if (project != null && project.IsDragAllowed(dragNode, dropNode, dropSide == DropSide.Inside)) return true; return false; }