예제 #1
0
        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();
            }
        }
예제 #2
0
        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);
        }