protected override void OnPreviewMouseDown(MouseButtonEventArgs e) { base.OnPreviewMouseDown(e); m_currentPosition = e.GetPosition(this); m_originPoint = m_currentPosition; m_hittestElement = this.HitTest <BaseNodeControl>(m_currentPosition); if (m_hittestElement != null) // if node based element is clicked { var connector = m_hittestElement as ConnectorControl; if (connector != null) { var sourceConnector = connector; // if connector is already connected and Ctrl key pressed - start nodes reconnection if (connector.ConnectionPoint.IsConnected && (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))) { var connections = m_connections.Where(c => c.Value.Source.Equals(connector) || c.Value.Destination.Equals(connector)).ToList(); if (connections.Any()) { var record = connections.First(); // this is not a misstake. // If this is Source connector for connection then virtual connection should start from // oposit connector which is Destination and vice versa. if (record.Value.Source.Equals(connector)) { sourceConnector = (ConnectorControl)record.Value.Destination; } else { sourceConnector = (ConnectorControl)record.Value.Source; } Diagram.Connections.Remove(record.Key); } } // if it is connector - create virtual connection // virtual elements excluded from hit test var virtualConnector = new VirtualConnectionPoint(sourceConnector) { X = m_currentPosition.X, Y = m_currentPosition.Y }; Children.Add(virtualConnector); var virtualConnection = new VirtualConnection(sourceConnector.ConnectionPoint); var virtualConnectionContainer = new ConnectionContainerControl(sourceConnector, virtualConnector, virtualConnection, false); m_connections.Add(virtualConnection, virtualConnectionContainer); Children.Add(virtualConnectionContainer); m_hittestElement = virtualConnector; } m_hittestElement.CaptureMouse(); } }
protected override void OnPreviewMouseUp(MouseButtonEventArgs e) { if (m_hittestElement != null) { m_hittestElement.ReleaseMouseCapture(); var point = m_hittestElement as VirtualConnectionPoint; if (point != null) { var hittest = this.AreaHitTest <ConnectorControl>(m_currentPosition, Constants.VirtualPointXOffset - 5); if (hittest != null && hittest.ConnectionPoint.CanConnect(point.SourceConnectionPoint)) { // if captured element is VirtualConnector and hittest element is ConnectionPoint - create connection var newConnection = m_diagram.ConnectionsFactory.CreateConnection(point.SourceConnectionPoint, hittest.ConnectionPoint); if (newConnection != null) { m_diagram.Connections.Add(newConnection); // add connection contrainer control to canvas var connectionContainer = new ConnectionContainerControl(point.SourceConnectorControl, hittest, newConnection); m_connections.Add(newConnection, connectionContainer); Children.Add(connectionContainer); } } var noneVirtualConnection = this.HitTest <ConnectionContainerControl>(m_currentPosition); if (noneVirtualConnection != null) { var oldSource = noneVirtualConnection.Source; var oldDestination = noneVirtualConnection.Destination; var connectionContext = noneVirtualConnection.Connection; ConnectorControl middleConnector = new ConnectorControl { X = m_currentPosition.X, Y = m_currentPosition.Y, Width = 10, Height = 10, ConnectionPoint = Activator.CreateInstance(noneVirtualConnection.Connection.StartPoint.GetType()) as IConnectionPoint }; Canvas.SetLeft(middleConnector, middleConnector.X - middleConnector.Width / 2); Canvas.SetTop(middleConnector, middleConnector.Y - middleConnector.Height / 2); Children.Remove(m_connections[connectionContext]); m_connections.Remove(connectionContext); Children.Add(middleConnector); var sourceToMiddle = m_diagram.ConnectionsFactory.CreateConnection( connectionContext.StartPoint, middleConnector.ConnectionPoint); var middleToTarget = m_diagram.ConnectionsFactory.CreateConnection( middleConnector.ConnectionPoint, connectionContext.EndPoint); m_diagram.Connections.Add(sourceToMiddle); m_diagram.Connections.Add(middleToTarget); var sourceToMiddleContainer = new ConnectionContainerControl(oldSource, middleConnector, sourceToMiddle); m_connections.Add(sourceToMiddle, sourceToMiddleContainer); Children.Add(sourceToMiddleContainer); var middleToTargetContainer = new ConnectionContainerControl(middleConnector, oldDestination, middleToTarget); m_connections.Add(middleToTarget, middleToTargetContainer); Children.Add(middleToTargetContainer); // add connection from original node to middle connection point var newConnection = m_diagram.ConnectionsFactory.CreateConnection(point.SourceConnectionPoint, middleConnector.ConnectionPoint); if (newConnection != null) { m_diagram.Connections.Add(newConnection); var connectionContainer = new ConnectionContainerControl(point.SourceConnectorControl, middleConnector, newConnection); m_connections.Add(newConnection, connectionContainer); Children.Add(connectionContainer); } } // remove virtual connection and point Children.Remove(point); var virtualConnection = m_connections.Keys.FirstOrDefault(k => k is VirtualConnection); if (virtualConnection != null) { Children.Remove(m_connections[virtualConnection]); m_connections.Remove(virtualConnection); } } var selectionRect = m_hittestElement as SelectionRect; if (selectionRect != null) // mass selection { double selectionStartX = m_currentPosition.X; double selectionStartY = m_currentPosition.Y; if (selectionRect.SelectionStartPoint.X < selectionStartX) { selectionStartX = selectionRect.SelectionStartPoint.X; } if (selectionRect.SelectionStartPoint.Y < selectionStartY) { selectionStartY = selectionRect.SelectionStartPoint.Y; } var startPoint = new Point(selectionStartX, selectionStartY); // find elements under selection rect var elements = this.AreaHitTest <NodeContainerControl>(startPoint, selectionRect.ActualWidth, selectionRect.ActualHeight); foreach (var coveredNode in elements.Select(n => n.Node)) { ToggleSelection(coveredNode, true); } // remove selection rectangle Children.Remove(selectionRect); } var node = m_hittestElement as NodeContainerControl; if (node != null && // single node selection Math.Abs(m_currentPosition.X - m_originPoint.X) <= SystemParameters.MinimumHorizontalDragDistance && Math.Abs(m_currentPosition.Y - m_originPoint.Y) <= SystemParameters.MinimumVerticalDragDistance) { if (m_selectedNodes.Count >= 1) // after mass selection remove selection from nodes other that clicked one { var removeSelection = m_selectedNodes.Where(n => !n.Equals(node.Node)).ToList(); foreach (var selectedNode in removeSelection) { ToggleSelection(selectedNode, false); } ToggleSelection(node.Node, true); } else { ToggleSelection(node.Node, !node.Node.IsSelected); } } var connectionCtrl = m_hittestElement as ConnectionContainerControl; if (connectionCtrl != null) // connections selection { var connections = m_connections.Where(c => c.Value.Equals(connectionCtrl)).Select(c => c.Key); foreach (var connection in connections) { connection.IsSelected = !connection.IsSelected; } } } else { // click on canvas clears selection foreach (var selectedNode in m_selectedNodes) { selectedNode.IsSelected = false; } m_selectedNodes.Clear(); } m_hittestElement = null; base.OnPreviewMouseUp(e); }