/// <summary> /// Occurs when a drag-and-drop operation is completed. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DragDropHandler(object sender, DragEventArgs e) { if (lastDragDropTarget != null) { lastDragDropTarget.BackColor = lastDragDropTargetBackColor; lastDragDropTarget = null; } var sourceNode = GetDragDropSourceNode(e); if (sourceNode == null) { MessageBox.Show(@"Drag & Drop Canceled: Unknown Source"); return; } var targetNode = GetDragDropTargetNode(e); switch (e.Effect) { case DragDropEffects.Copy: DoDragDropCopy((dynamic)sourceNode, (dynamic)targetNode); break; case DragDropEffects.Move: DoDragDropMove((dynamic)sourceNode, (dynamic)targetNode); break; } }
// ReSharper disable once UnusedParameter.Local private void AfterSelectImplementation(JTokenTreeNode node, TreeViewEventArgs e) { AfterSelect?.Invoke(this, new AfterSelectEventArgs( $"{node.JTokenTag.Type}", $"{node.JTokenTag.Type}", () => $"{node.JTokenTag}")); }
/// <summary> /// Implementation of "paste and replace" action. /// </summary> /// <param name="node"></param> public static void ClipboardPasteReplace(this JTokenTreeNode node) { node.ClipboardPaste( jt => node.JTokenTag.Replace(jt), n => node.InsertInParent(n, true) ); }
/// <summary> /// Implementation of "paste" action using 2 delegates for the concrete action on JToken tree and TreeView. /// </summary> /// <param name="node"></param> /// <param name="pasteJTokenImplementation">Implementation of paste action in the JToken tree.</param> /// <param name="pasteTreeNodeImplementation">Implementation of paste action in the treeView.</param> private static void ClipboardPaste(this JTokenTreeNode node, Action <JToken> pasteJTokenImplementation, Action <TreeNode> pasteTreeNodeImplementation) { var sourceJTokenTreeNode = EditorClipboard <JTokenTreeNode> .Get(); var jTokenSource = sourceJTokenTreeNode.JTokenTag.DeepClone(); try { pasteJTokenImplementation(jTokenSource); } catch (Exception exception) { // If cut was asked, the clipboard is now empty and source should be inserted again in clipboard if (EditorClipboard <JTokenTreeNode> .IsEmpty()) { EditorClipboard <JTokenTreeNode> .Set(sourceJTokenTreeNode, false); } throw new JTokenTreeNodePasteException(exception); } var treeView = node.TreeView; treeView.BeginUpdate(); pasteTreeNodeImplementation(JsonTreeNodeFactory.Create(jTokenSource)); treeView.EndUpdate(); // If cut was asked, the clipboard is now empty and source should be removed from treeview if (EditorClipboard <JTokenTreeNode> .IsEmpty()) { sourceJTokenTreeNode.EditDelete(); } }
/// <summary> /// Implementation of "paste into" action. /// </summary> /// <param name="node"></param> public static void ClipboardPasteInto(this JTokenTreeNode node) { node.ClipboardPaste( jt => ((JContainer)node.JTokenTag).AddFirst(jt), n => node.InsertInCurrent(n) ); }
/// <summary> /// Implementation of "paste before" action. /// </summary> /// <param name="node"></param> public static void ClipboardPasteBefore(this JTokenTreeNode node) { node.ClipboardPaste( jt => node.JTokenTag.AddBeforeSelf(jt), n => node.InsertInParent(n, true) ); }
/// <summary> /// Implementation of "paste after" action. /// </summary> /// <param name="node">Reference node for the paste.</param> public static void ClipboardPasteAfter(this JTokenTreeNode node) { node.ClipboardPaste( jt => node.JTokenTag.AddAfterSelf(jt), n => node.InsertInParent(n, false) ); }
private bool IsDragDropValid(JTokenTreeNode sourceNode, JTokenTreeNode targetNode, DragDropEffects effect) { if (sourceNode == null || targetNode == null) { return(false); } if (sourceNode.JTokenTag is JProperty) { return(targetNode.JTokenTag is JObject); } if (sourceNode.JTokenTag is JObject) { switch (effect) { case DragDropEffects.Copy: return(targetNode.JTokenTag is JArray); case DragDropEffects.Move: return(!(targetNode.JTokenTag.Parent is JProperty) && targetNode.JTokenTag is JArray); } } if (sourceNode.JTokenTag is JArray) { switch (effect) { case DragDropEffects.Copy: return(targetNode.JTokenTag is JArray); case DragDropEffects.Move: return(!(targetNode.JTokenTag.Parent is JProperty) && targetNode.JTokenTag is JArray); } } if (sourceNode.JTokenTag is JValue) { switch (effect) { case DragDropEffects.Copy: return(targetNode.JTokenTag is JArray); case DragDropEffects.Move: return(!(targetNode.JTokenTag.Parent is JProperty) && targetNode.JTokenTag is JArray); } } return(false); }
/// <summary> /// Implementation of "delete" action. /// </summary> /// <param name="node"></param> public static void EditDelete(this JTokenTreeNode node) { if (node == null) { return; } try { node.JTokenTag.Remove(); } catch (Exception exception) { throw new JTokenTreeNodeDeleteException(exception); } var treeView = node.TreeView; treeView.BeginUpdate(); node.CleanParentTreeNode(); treeView.EndUpdate(); }
/// <summary> /// Occurs when an object is dragged over the control's bounds. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void DragOverHandler(object sender, DragEventArgs e) { var targetNode = GetDragDropTargetNode(e); if (targetNode == null) { e.Effect = DragDropEffects.None; if (lastDragDropTarget != null) { lastDragDropTarget.BackColor = lastDragDropTargetBackColor; } lastDragDropTarget = null; return; } var keyState = (KeyStates)e.KeyState; if (keyState.HasFlag(KeyStates.Control | KeyStates.Shift)) { e.Effect = DragDropEffects.None; } else if (keyState.HasFlag(KeyStates.Control)) { e.Effect = DragDropEffects.Copy; } else if (keyState.HasFlag(KeyStates.Shift)) { e.Effect = DragDropEffects.Move; } else { e.Effect = DragDropEffects.Move; } var sourceNode = GetDragDropSourceNode(e); if (targetNode == lastDragDropTarget) { if (!targetNode.IsExpanded && DateTime.Now - lastDragOverDateTime >= dragDropExpandDelay) { targetNode.Expand(); } if (IsDragDropValid(sourceNode, targetNode, e.Effect)) { lastDragDropTargetBackColor = targetNode.BackColor; targetNode.BackColor = Color.BlueViolet; } else { targetNode.BackColor = lastDragDropTargetBackColor; e.Effect = DragDropEffects.None; } } else { lastDragDropTarget = targetNode; lastDragOverDateTime = DateTime.Now; if (IsDragDropValid(sourceNode, targetNode, e.Effect)) { lastDragDropTargetBackColor = targetNode.BackColor; targetNode.BackColor = Color.BlueViolet; } else { targetNode.BackColor = lastDragDropTargetBackColor; e.Effect = DragDropEffects.None; } } if (lastDragDropTarget != null) { lastDragDropTarget.BackColor = lastDragDropTargetBackColor; } }
private void DoDragDropMove(JTokenTreeNode sourceNode, JTokenTreeNode targetNode) { // TODO: Move sourceNode to target MessageBox.Show(@"Drag & Drop: Unmanaged Move"); }
/// <summary> /// Catches all unmanaged copies. /// </summary> /// <param name="sourceNode"></param> /// <param name="targetNode"></param> private void DoDragDropCopy(JTokenTreeNode sourceNode, JTokenTreeNode targetNode) { MessageBox.Show(@"Drag & Drop: Unmanaged Copy"); }
/// <summary> /// Implementation of "cut" action /// </summary> /// <param name="node"></param> public static JTokenTreeNode ClipboardCut(this JTokenTreeNode node) { EditorClipboard <JTokenTreeNode> .Set(node, false); return(node); }