/// <summary> /// Handles when a mouse button is let go of. /// </summary> protected override void OnMouseUp(MouseEventArgs e) { // check if we were dragging or copying an existing node if(e.Button ==MouseButtons.Right && _movedNode !=null || e.Button ==MouseButtons.Left && _copiedNode !=null || e.Button ==MouseButtons.Left && _clipboardPasteMode) { // if we have a valid target node continue if(_dragTargetNode !=null) { Node sourcenode= null; if(_movedNode !=null) sourcenode= _movedNode; else if(_copiedNode !=null) sourcenode= _keyShiftIsDown ? (Nodes.Node)_copiedNode.CloneBranch() : (Nodes.Node)_copiedNode.Clone(); else if(_clipboardPasteMode) sourcenode= _keyShiftIsDown ? (Nodes.Node)_clipboardNode.CloneBranch() : (Nodes.Node)_clipboardNode.Clone(); // move the dragged node to the target node, according to the attach mode switch(_dragAttachMode) { // the node will be placed above the traget node case(NodeAttachMode.Top): if(_movedNode !=null) { if(_keyShiftIsDown) { _movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode); } else { if(!_movedNode.ExtractNode()) throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted); } } int n= _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node); _dragTargetNode.Node.Parent.AddChild(_dragTargetNode.Node.ParentConnector, sourcenode, n); LayoutChanged(); break; // the node will be placed below the target node case(NodeAttachMode.Bottom): if(_movedNode !=null) { if(_keyShiftIsDown) { _movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode); } else { if(!_movedNode.ExtractNode()) throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted); } } int m= _dragTargetNode.Node.ParentConnector.GetChildIndex(_dragTargetNode.Node); _dragTargetNode.Node.Parent.AddChild(_dragTargetNode.Node.ParentConnector, sourcenode, m +1); LayoutChanged(); break; // the node will be placed in front of the target node case(NodeAttachMode.Left): if(_movedNode !=null) { if(_keyShiftIsDown) { _movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode); } else { if(!_movedNode.ExtractNode()) throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted); } } Node parent= _dragTargetNode.Node.Parent; Node.Connector conn= _dragTargetNode.Node.ParentConnector; int o= conn.GetChildIndex(_dragTargetNode.Node); parent.RemoveChild(conn, _dragTargetNode.Node); parent.AddChild(conn, sourcenode, o); sourcenode.AddChild(sourcenode.DefaultConnector, _dragTargetNode.Node); break; // the node will simply attached to the target node case(NodeAttachMode.Right): if(_movedNode !=null) { if(_keyShiftIsDown) { _movedNode.Parent.RemoveChild(_movedNode.ParentConnector, _movedNode); } else { if(!_movedNode.ExtractNode()) throw new Exception(Resources.ExceptionNodeCouldNotBeExtracted); } } _dragTargetNode.Node.AddChild(_dragTargetConnector, sourcenode); LayoutChanged(); break; } // update the node's label sourcenode.OnPropertyValueChanged(false); } // reset all the drag data if(!_clipboardPasteMode) { _copiedNode= null; _movedNode= null; _dragTargetNode= null; _dragNodeDefaults= null; _movedNodeGraph= null; } // redraw the graph Invalidate(); } Cursor= Cursors.Hand; base.OnMouseUp(e); }
/// <summary> /// Handles when the mouse is moved. /// </summary> protected override void OnMouseMove(MouseEventArgs e) { if(_lostFocus) { _lostFocus= false; // update the last ouse position _lastMousePosition= e.Location; base.OnMouseMove(e); return; } // returns the mouse under the mouse cursor NodeViewData nodeFound= _rootNode.IsInside(e.Location); // clear previously stored node which can cause problems when dragging to another view _dragTargetNode= null; // if a different node is the current one, update it if(nodeFound !=_currentNode) { _currentNode= nodeFound; // if enabled show the tooltip for the node if(Settings.Default.ShowNodeToolTips) { if(_currentNode ==null) { toolTip.Hide(this); } else { if(_currentNode.Node.ToolTip !=string.Empty) toolTip.Show(_currentNode.Node.ToolTip, this, new Point( (int)_currentNode.DisplayBoundingBox.X -20, (int)_currentNode.DisplayBoundingBox.Y -30 )); } } Invalidate(); } // check if we are currently dragging the graph if(e.Button ==MouseButtons.Left && _lastMousePosition !=e.Location && !_keyControlIsDown && _copiedNode ==null) { _wasDragged= true; // move the graph according to the last mouse position _nodeLayoutManager.Offset= new PointF(_nodeLayoutManager.Offset.X - (_lastMousePosition.X - e.X), _nodeLayoutManager.Offset.Y - (_lastMousePosition.Y - e.Y)); Invalidate(); } // check if we start duplicating an existing node step 1 else if(e.Button ==MouseButtons.Left && _keyControlIsDown && _lastMousePosition !=e.Location && _copiedNode ==null && _currentNode !=null && !(_currentNode.Node is BehaviorNode)) { _copiedNode= _currentNode.Node; // create the layout manager used to draw the graph _movedNodeGraph= new NodeLayoutManager(_copiedNode.CloneBranch().CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true); _movedNodeGraph.Scale= 0.3f; _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; // use the existing node as the node defaults _dragNodeDefaults= _copiedNode; Invalidate(); } // check if we are duplicating an existing node step 2 else if(e.Button ==MouseButtons.Left && _keyControlIsDown && _copiedNode !=null) { _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; _dragTargetNode= _currentNode; Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow; //Point movedGraphGraphPos= new Point(e.Location.X + _movedNodeGraph.Offset.X, e.Location.Y + _movedNodeGraph.Offset.Y /-2); //_movedNodeGraph.Location= movedGraphGraphPos; Invalidate(); } // check if we start dragging an existing node step 1 else if(e.Button ==MouseButtons.Right && _lastMousePosition !=e.Location && _movedNode ==null && _currentNode !=null && !(_currentNode.Node is BehaviorNode) && (_keyShiftIsDown || _currentNode.Node.ParentCanAdoptChildren)) { _movedNode= _currentNode.Node; // create the layout manager used to draw the graph _movedNodeGraph= new NodeLayoutManager(_movedNode.CloneBranch().CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true); _movedNodeGraph.Scale= 0.3f; _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; // use the existing node as the node defaults _dragNodeDefaults= _movedNode; Invalidate(); } // check if we are dragging an existing node step 2 else if(e.Button ==MouseButtons.Right && _movedNode !=null) { _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; _dragTargetNode= _currentNode; Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow; Invalidate(); } else if(_clipboardPasteMode) { _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; _dragTargetNode= _currentNode; Cursor= _currentNode ==null ? Cursors.No : Cursors.Arrow; Invalidate(); } // update the last ouse position _lastMousePosition= e.Location; base.OnMouseMove(e); }
/// <summary> /// Handles when a key is pressed. /// </summary> protected override void OnKeyDown(KeyEventArgs e) { switch(e.KeyCode) { // store when the control key is pressed case(Keys.ControlKey): _keyControlIsDown= true; if(_copiedNode ==null && _movedNode ==null) Cursor= Cursors.Arrow; break; // store when the shift key is pressed case(Keys.ShiftKey): _keyShiftIsDown= true; // update the drawn graph for dragging and duplicating if(_movedNodeGraph !=null) { _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; Invalidate(); } break; // copy to clipboard case(Keys.C): if(_keyControlIsDown && _selectedNode !=null) { _clipboardNode= _keyShiftIsDown ? (Node)_selectedNode.Node.CloneBranch() : (Node)_selectedNode.Node.Clone(); } break; // paste from clipboard case(Keys.V): if(!_clipboardPasteMode) { _clipboardPasteMode= _keyControlIsDown && _clipboardNode !=null; if(_clipboardPasteMode) { // create the layout manager used to draw the graph _movedNodeGraph= new NodeLayoutManager(_clipboardNode.CreateNodeViewData(null, _rootNode.RootBehavior), _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, true); _movedNodeGraph.Scale= 0.3f; _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; // use the existing node as the node defaults _dragNodeDefaults= _clipboardNode; Invalidate(); } } break; // cut to clipboard case(Keys.X): if(_keyControlIsDown && _selectedNode !=null) { _clipboardNode= _keyShiftIsDown ? (Node)_selectedNode.Node.CloneBranch() : (Node)_selectedNode.Node.Clone(); // store the selected node Node node= _selectedNode.Node; // clear the selected and current node _selectedNode= null; _currentNode= null; if(_keyShiftIsDown) { // remove the node node.Parent.RemoveChild(node.ParentConnector, node); // call the ClickNode event to delselect the node in the editor if(ClickNode !=null) ClickNode(null); } else { if(node.ExtractNode()) { // call the ClickNode event to delselect the node in the editor if(ClickNode !=null) ClickNode(null); } } } break; // handle when the delete key is pressed case(Keys.Delete): // when we have a node selected which is not the root node, continue if(_selectedNode !=null && _selectedNode.Node.Parent !=null) { // check whether we have to delete an event or a node if(_selectedNode.Node.SelectedSubItem ==null) { // store the selected node Node node= _selectedNode.Node; // clear the selected and current node _selectedNode= null; _currentNode= null; if(_keyShiftIsDown) { // remove the node node.Parent.RemoveChild(node.ParentConnector, node); // call the ClickNode event to delselect the node in the editor if(ClickNode !=null) ClickNode(null); } else { if(node.ExtractNode()) { // call the ClickNode event to delselect the node in the editor if(ClickNode !=null) ClickNode(null); } } } else { // just let the node delete the selected subitem if(_selectedNode.Node.RemoveSelectedSubItem()) { _selectedNode.Node.BehaviorWasModified(); // call the ClickNode event to select the node instead of the deleted subitem if(ClickNode !=null) ClickNode(_selectedNode); } } // the layout needs to be recalculated LayoutChanged(); } break; default: base.OnKeyDown(e); break; } }
private void imageButton_Click(object sender, EventArgs e) { if(saveImageDialog.ShowDialog() ==DialogResult.OK) { NodeLayoutManager nlm= new NodeLayoutManager(_nodeLayoutManager.RootNodeLayout, _nodeLayoutManager.EdgePen, _nodeLayoutManager.EdgePenReadOnly, false); nlm.Offset= new PointF(1.0f, 1.0f); using(Graphics g= CreateGraphics()) { nlm.UpdateLayout(g); } SizeF totalSize= nlm.RootNodeLayout.GetTotalSize(nlm.Padding.Width, int.MaxValue); Size newimageSize= new Size( (int) Math.Ceiling(totalSize.Width) +2, (int) Math.Ceiling(totalSize.Height) +2 ); Graphics formGraphics= null; IntPtr hdc= new IntPtr(); Image img= null; bool needsSave= true; if(saveImageDialog.FilterIndex ==1) { formGraphics= CreateGraphics(); hdc= formGraphics.GetHdc(); img= new Metafile(saveImageDialog.FileName, hdc); needsSave= false; } else if(saveImageDialog.FilterIndex ==2) { img= new Bitmap(newimageSize.Width, newimageSize.Height); } using(Graphics graphics= Graphics.FromImage(img)) { nlm.DrawGraph(graphics, null, null, new PointF()); } if(needsSave) img.Save(saveImageDialog.FileName); img.Dispose(); if(formGraphics !=null) { formGraphics.ReleaseHdc(hdc); formGraphics.Dispose(); } } }
/// <summary> /// Handles when a key is released. /// </summary> protected override void OnKeyUp(KeyEventArgs e) { switch(e.KeyCode) { // store when the control key is released case(Keys.ControlKey): _keyControlIsDown= false; if(_copiedNode ==null && _movedNode ==null) Cursor= Cursors.Hand; break; // store when the shift key is released case(Keys.ShiftKey): _keyShiftIsDown= false; // update the drawn graph for dragging and duplicating if(_movedNodeGraph !=null) { _movedNodeGraph.RenderDepth= _keyShiftIsDown ? int.MaxValue : 0; Invalidate(); } break; // paste from clipboard case(Keys.V): _clipboardPasteMode= false; // reset all the drag data _copiedNode= null; _movedNode= null; _dragTargetNode= null; _dragNodeDefaults= null; _movedNodeGraph= null; // redraw the graph Invalidate(); break; default: base.OnKeyUp(e); break; } }