private void AddConnectionFromXml(XMLConnection xmlConnection) { // Find node endpoints for the connection var canvasModules = Children.OfType <CanvasModule>(); RenderNode start = null; RenderNode end = null; foreach (var canvasModule in canvasModules) { if (canvasModule.TextBoxDisplayName.Text == xmlConnection.Output.ModuleName) { start = canvasModule.OutputNodes.Where(t => t.Node.Identity == xmlConnection.Output.Identity).FirstOrDefault(); } else if (canvasModule.TextBoxDisplayName.Text == xmlConnection.Input.ModuleName) { end = canvasModule.InputNodes.Where(t => t.Node.Identity == xmlConnection.Input.Identity).FirstOrDefault(); } if (start != null && end != null) { break; } } if (start == null || end == null) { throw new XmlException("Cannot re-establish module connection:" + " one of the endpoints were not found"); } // Finalize connection StartConnection(start); FinishConnection(end); }
public Connection(WorkflowCanvas canvas, RenderNode startPoint, RenderNode endPoint, ConnectingLine line) { this.Canvas = canvas; Line = line; if (startPoint.Node.GetConnectionType() == INodeConnectionType.OUTPUT && endPoint.Node.GetConnectionType() == INodeConnectionType.INPUT) { Input = (BaseInputNode)endPoint.Node; Output = (BaseOutputNode)startPoint.Node; Start = startPoint; End = endPoint; } else if (startPoint.Node.GetConnectionType() == INodeConnectionType.INPUT && endPoint.Node.GetConnectionType() == INodeConnectionType.OUTPUT) { Input = (BaseInputNode)startPoint.Node; Output = (BaseOutputNode)endPoint.Node; Start = endPoint; End = startPoint; } contextMenu = new ContextMenu(); MenuItem item = new MenuItem(); item.Header = "Disconnect"; contextMenu.Items.Add(item); item.Click += delegate { Disconnect(); }; }
/// <summary> /// Starts a new connection from the specified node. This will trigger /// a temporary line to be drawn from the starting node to the mouse /// cursor. If this node is already connected, this method will have /// no effect. /// </summary> /// <param name="node">The starting node.</param> public void StartConnection(RenderNode node) { // Cannot connect an already-connected node if (node.Node.IsConnected()) { return; } logger.Info($"Starting connection NodeParent:{node.Parent.TextBoxDisplayName.Text} NodeName: {node.Node.GetDisplayName()}"); StartNode = node; TempLine.SetVisibility(Visibility.Visible); TempLine.SetBrush(node.Visual.Fill); TempLine.Line.StrokeThickness = node.Visual.Width / LINE_THICKNESS_FRACTION; ConnectionStartPos = node.Visual.TransformToAncestor(this).Transform(new Point(0, 0)); ConnectionStartPos.Y += node.Visual.ActualHeight / 2; if (node.Node.GetConnectionType() == INodeConnectionType.INPUT) { ConnectionStartPos.X -= node.Visual.ActualWidth / 4; TempLine.Redraw(Mouse.GetPosition(this), ConnectionStartPos); TempLine.SetCanvasPos(Mouse.GetPosition(this), ConnectionStartPos); } else { ConnectionStartPos.X += node.Visual.ActualWidth / 2; TempLine.Redraw(ConnectionStartPos, Mouse.GetPosition(this)); TempLine.SetCanvasPos(ConnectionStartPos, Mouse.GetPosition(this)); } }
/// <summary> /// Finishes a temporary connection started by <see cref="StartConnection"/>. /// This will solidify a connection and add it to the active connections /// list to prevent redrawing of static lines. /// </summary> /// <param name="node">The node.</param> public void FinishConnection(RenderNode node) { ConnectingLine connectingLine = new ConnectingLine(TempLine.Line.Stroke); connectingLine.Line.StrokeThickness = node.Visual.Width / LINE_THICKNESS_FRACTION; Connection connection = new Connection(this, StartNode, node, connectingLine); if (connection.IsValid()) { bool success = connection.Connect(); if (success) { RedrawLine(connection); Connections.Add(connection); Children.Add(connection.Line.Line); Children.Add(connection.Line.Arrowhead); connection.Start.Parent.OnModuleMove += OnConnectedModuleMove; connection.End.Parent.OnModuleMove += OnConnectedModuleMove; } } // else let it fall out of scope to be garbage collected StartNode = null; TempLine.SetVisibility(Visibility.Collapsed); }
private static void WriteXmlNode(XmlWriter writer, RenderNode node) { writer.WriteAttributeString("ModuleName", node.Parent.TextBoxDisplayName.Text); var idx = -1; if (node.Node.GetConnectionType() == INodeConnectionType.OUTPUT) { idx = node.Parent.OutputNodes.IndexOf(node); } else { idx = node.Parent.InputNodes.IndexOf(node); } if (idx < 0) { throw new XmlException("Could not serialize connection: Node not found in module"); } writer.WriteAttributeString("Index", idx.ToString()); writer.WriteAttributeString("Identity", node.Node.Identity.ToString()); }
protected override void OnMouseUp(MouseButtonEventArgs e) { base.OnMouseUp(e); if (IsPanning) { IsPanning = false; e.Handled = true; } if (TempLine.Visibility != Visibility.Collapsed) { // Must be drawing a temp line e.Handled = true; TempLine.SetVisibility(Visibility.Collapsed); // Attempt to get a RenderNode under the mouse // Ensure that the RenderNode isn't from the same CanvasModule RenderNode endpoint = null; VisualTreeHelper.HitTest(this, null, (HitTestResult result) => { if (result.VisualHit.GetType().IsAssignableFrom(typeof(Ellipse))) { var ellipse = result.VisualHit as Ellipse; if (!StartNode.Parent.ContainsNodeVisual(ellipse)) { endpoint = VisualHelper.FindParentOfType <CanvasModule>(ellipse) .GetRenderNode(ellipse); return(HitTestResultBehavior.Stop); } } return(HitTestResultBehavior.Continue); }, new PointHitTestParameters(e.GetPosition(this))); if (endpoint != null) { FinishConnection(endpoint); } } }
protected override void OnMouseDown(MouseButtonEventArgs e) { logger.Trace("Entered"); base.OnMouseDown(e); if (Parent != WfCanvas) { return; } // Keyboard.ClearFocus(); //e.Handled = true; if (e.OriginalSource == PageImage) { if (!this.IsFocused) { if (this.Focus()) { IsActive = true; } } } else if (e.OriginalSource.GetType() == typeof(Ellipse)) { IsActive = true; } if (e.ClickCount > 1) { logger.Trace("doubleclick_1"); OnDoubleClick(this, e); return; } /* * if (MouseButtonState.Pressed == e.RightButton) * { * logger.Info("this.PageImage.ContextMenu.IsOpen = true"); * if (!this.PageImage.ContextMenu.IsOpen) * this.PageImage.ContextMenu.IsOpen = true; * } */ if (!IsDragged && MouseButtonState.Pressed == e.LeftButton) { RelMousePos = e.MouseDevice.GetPosition(this); // Use a hit test to determine if node HitTestResult result = VisualTreeHelper.HitTest( this, e.MouseDevice.GetPosition(this)); if (result.VisualHit.GetType().IsAssignableFrom(typeof(Ellipse))) { Ellipse shape = (Ellipse)result.VisualHit; RenderNode node = null; foreach (var inputNode in InputNodes) { if (inputNode.Visual == shape) { node = inputNode; } } foreach (var outputNode in OutputNodes) { if (outputNode.Visual == shape) { node = outputNode; } } logger.Info("Calling delete OnNodeDragStart to start drawing connection line "); OnNodeStartConnectionLine(node ?? throw new Exception("Hit ellipse shape is not in a node map")); return; } // If not, just drag the module IsDragged = true; logger.Info("IsDragged ={0}", IsDragged); WorkflowCanvas.SetZIndex(this, 2); var window = Window.GetWindow(this); if (window != null) { window.MouseUp += OnCanvasDragDrop; } } }