/// <summary>
        ///
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseUp(MouseEventArgs e)
        {
            if (IsActive)
            {
                DeactivateTool();

                //whatever comes hereafter, a compund command is the most economic approach
                CompoundCommand package = new CompoundCommand(this.Controller);

                //let's see if the connection endpoints hit other connectors
                //note that the following can be done because the actual connection has not been created yet
                //otherwise the search would find the endpoints of the newly created connection, which
                //would create a loop and a stack overflow!
                IConnector startConnector = Selection.FindConnectorAt(initialPoint);
                IConnector endConnector   = Selection.FindConnectorAt(e.Location);

                #region Create the new connection
                Connection           cn     = new Connection(this.initialPoint, e.Location, this.Controller.Model);
                AddConnectionCommand newcon = new AddConnectionCommand(this.Controller, cn);
                package.Commands.Add(newcon);
                #endregion

                #region Initial attachment?
                if (startConnector != null)
                {
                    BindConnectorsCommand bindStart = new BindConnectorsCommand(this.Controller, startConnector, cn.From);
                    package.Commands.Add(bindStart);
                }
                #endregion

                #region Final attachment?
                if (endConnector != null)
                {
                    BindConnectorsCommand bindEnd = new BindConnectorsCommand(this.Controller, endConnector, cn.To);
                    package.Commands.Add(bindEnd);
                }
                #endregion
                package.Text = "New connection";
                this.Controller.UndoManager.AddUndoCommand(package);

                //do it all
                package.Redo();

                //reset highlight of the found connector
                if (foundConnector != null)
                {
                    foundConnector.Hovered = false;
                }
                //drop the painted ghost
                Controller.View.ResetGhost();
                //release other tools
                this.UnsuspendTools();
            }
        }
        /// <summary>
        /// When an entity is moved there are various possibilities:
        /// <list type="bullet">
        /// <item>
        /// <term>a connector is moved</term>
        /// <description>in this case the moved connector can only be part of a onnection because moving shape-connectors is not allowed unless by means of the <see cref="ConnectorMoverTool"/>.
        /// If a connector attached to a connection is moved we have the following fork:
        /// <list type="bullet">
        /// <item>the connector was attached</item>
        /// <description>the connector has a parent and needs to be detached before being moved and eventually attached to another connector</description>
        /// <item>the connector is moved</item>
        /// <description>this is a standard motion and is similar for any <see cref="IDiagramEntity"/>
        /// </description>
        /// <item>the connector ends up somewhere near another connector and will become attached to it</item>
        /// <description>the connector in the proximity of the moved connector will become the parent of it. Note that we previously detached any binding and that a connector can have only one parent.</description>
        /// </list>
        /// </description>
        /// </item>
        /// <item>an entity is moved</item>
        /// <description>the normal <see cref="MoveCommand"/> can be used</description>
        /// <item>a set of entities is moved</item>
        /// <description>we need to create a bundle to package the entities and then use the <see cref="MoveCommand"/></description>
        /// </list>
        /// Several important remarks are in order here:
        /// <list type="bullet">
        /// <item>a connector can have only one parent</item>
        /// <item>we need to package a move action in a command but this command needs NOT to be performed (i.e. call the Redo() method) because the motion already occured through the MouseMove handler. Because of this situation we cannot perform a Redo() on the full package since it would move the entities twice. Hence, commands are execute just after their creation (except for the move).
        /// <item>when the stack of actions are undone the stack has to be reverted</item>
        /// </item>
        /// <item>whatever the situation is, the most economical way to code the different cases is by means of a <see cref="CompoundCommand"/> object</item>
        /// </list>
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseUp(MouseEventArgs e)
        {
            if(IsActive)
            {
                DeactivateTool();
                //creation of the total undoredo package
                CompoundCommand package = new CompoundCommand(this.Controller);
                string message = string.Empty;
                //notice that the connector can only be a connection connector because of the MouseDown check above
                if(connectorMove)
                {
                    #region We are moving a connection-connector

                    #region Is the connector attached?
                    //detach only if there is a parent different than a connection; the join of a chained connection is allowed to move
                    if( Selection.Connector.AttachedTo != null && !typeof(IConnection).IsInstanceOfType(Selection.Connector.AttachedTo))
                    {
                        DetachConnectorCommand detach = new DetachConnectorCommand(this.Controller, Selection.Connector.AttachedTo, Selection.Connector);
                        detach.Redo();
                        package.Commands.Add(detach);

                    }
                    #endregion

                    #region The moving part
                    //a bundle might look like overkill here but it makes the coding model uniform
                    Bundle bundle = new Bundle(Controller.Model);
                    bundle.Entities.Add(Selection.Connector);
                    MoveCommand move = new MoveCommand(this.Controller, bundle, new Point(lastPoint.X - initialPoint.X, lastPoint.Y - initialPoint.Y));
                    //no Redo() necessary here!
                    package.Commands.Add(move);
                    #endregion

                    #region The re-attachment near another connector
                    //let's see if the connection endpoints hit other connectors (different than the selected one!)
                    //define a predicate delegate to filter things out otherwise the hit will return the moved connector which would results
                    //in a stack overflow later on
                    Predicate<IConnector> predicate =
                        delegate(IConnector conn)
                        {
                            //whatever, except itself and any children of the moved connector
                            //since this would entail a child becoming a parent!
                            if(conn.Hit(e.Location) && conn != Selection.Connector && !Selection.Connector.AttachedConnectors.Contains(conn))
                                return true;
                            return false;
                        };
                    //find it!
                    IConnector parentConnector = Selection.FindConnector(predicate);

                    if(parentConnector != null) //aha, there's an attachment
                    {
                        BindConnectorsCommand binder = new BindConnectorsCommand(this.Controller, parentConnector, Selection.Connector);
                        package.Commands.Add(binder);
                        binder.Redo(); //this one is necessary since the redo cannot be performed on the whole compound command
                    }
                    #endregion

                    message = "Connector move";
                    #endregion
                }
                else
                {
                    #region We are moving entities other than a connector
                    Bundle bundle = new Bundle(Controller.Model);
                    bundle.Entities.AddRange(Selection.SelectedItems);
                    MoveCommand cmd = new MoveCommand(this.Controller, bundle, new Point(lastPoint.X - initialPoint.X, lastPoint.Y - initialPoint.Y));
                    package.Commands.Add(cmd);
                    //not necessary to perform the Redo action of the command since the mouse-move already moved the bundle!
                    #endregion

                    message = "Entities move";
                }
                //reset the hovered connector, if any
                if (hoveredConnector != null)
                    hoveredConnector.Hovered = false;
                package.Text = message;
                //whatever the content of the package we add it to the undo history
                this.Controller.UndoManager.AddUndoCommand(package);

                //show the tracker again
                this.Controller.View.ShowTracker();

            }
        }
Exemple #3
0
        /// <summary>
        /// When an entity is moved there are various possibilities:
        /// <list type="bullet">
        /// <item>
        /// <term>a connector is moved</term>
        /// <description>in this case the moved connector can only be part of a onnection because moving shape-connectors is not allowed unless by means of the <see cref="ConnectorMoverTool"/>.
        /// If a connector attached to a connection is moved we have the following fork:
        /// <list type="bullet">
        /// <item>the connector was attached</item>
        /// <description>the connector has a parent and needs to be detached before being moved and eventually attached to another connector</description>
        /// <item>the connector is moved</item>
        /// <description>this is a standard motion and is similar for any <see cref="IDiagramEntity"/>
        /// </description>
        /// <item>the connector ends up somewhere near another connector and will become attached to it</item>
        /// <description>the connector in the proximity of the moved connector will become the parent of it. Note that we previously detached any binding and that a connector can have only one parent.</description>
        /// </list>
        /// </description>
        /// </item>
        /// <item>an entity is moved</item>
        /// <description>the normal <see cref="MoveCommand"/> can be used</description>
        /// <item>a set of entities is moved</item>
        /// <description>we need to create a bundle to package the entities and then use the <see cref="MoveCommand"/></description>
        /// </list>
        /// Several important remarks are in order here:
        /// <list type="bullet">
        /// <item>a connector can have only one parent</item>
        /// <item>we need to package a move action in a command but this command needs NOT to be performed (i.e. call the Redo() method) because the motion already occured through the MouseMove handler. Because of this situation we cannot perform a Redo() on the full package since it would move the entities twice. Hence, commands are execute just after their creation (except for the move).
        /// <item>when the stack of actions are undone the stack has to be reverted</item>
        /// </item>
        /// <item>whatever the situation is, the most economical way to code the different cases is by means of a <see cref="CompoundCommand"/> object</item>
        /// </list>
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseUp(MouseEventArgs e)
        {
            if (IsActive)
            {
                DeactivateTool();
                //creation of the total undoredo package
                CompoundCommand package = new CompoundCommand(this.Controller);
                string          message = string.Empty;
                //notice that the connector can only be a connection connector because of the MouseDown check above
                if (connectorMove)
                {
                    #region We are moving a connection-connector

                    #region Is the connector attached?
                    //detach only if there is a parent different than a connection; the join of a chained connection is allowed to move
                    if (Selection.Connector.AttachedTo != null && !typeof(IConnection).IsInstanceOfType(Selection.Connector.AttachedTo))
                    {
                        DetachConnectorCommand detach = new DetachConnectorCommand(this.Controller, Selection.Connector.AttachedTo, Selection.Connector);
                        detach.Redo();
                        package.Commands.Add(detach);
                    }
                    #endregion

                    #region The moving part
                    //a bundle might look like overkill here but it makes the coding model uniform
                    Bundle bundle = new Bundle(Controller.Model);
                    bundle.Entities.Add(Selection.Connector);
                    MoveCommand move = new MoveCommand(this.Controller, bundle, new Point(lastPoint.X - initialPoint.X, lastPoint.Y - initialPoint.Y));
                    //no Redo() necessary here!
                    package.Commands.Add(move);
                    #endregion

                    #region The re-attachment near another connector
                    //let's see if the connection endpoints hit other connectors (different than the selected one!)
                    //define a predicate delegate to filter things out otherwise the hit will return the moved connector which would results
                    //in a stack overflow later on
                    Predicate <IConnector> predicate =
                        delegate(IConnector conn)
                    {
                        //whatever, except itself and any children of the moved connector
                        //since this would entail a child becoming a parent!
                        if (conn.Hit(e.Location) && conn != Selection.Connector && !Selection.Connector.AttachedConnectors.Contains(conn))
                        {
                            return(true);
                        }
                        return(false);
                    };
                    //find it!
                    IConnector parentConnector = Selection.FindConnector(predicate);

                    if (parentConnector != null) //aha, there's an attachment
                    {
                        BindConnectorsCommand binder = new BindConnectorsCommand(this.Controller, parentConnector, Selection.Connector);
                        package.Commands.Add(binder);
                        binder.Redo(); //this one is necessary since the redo cannot be performed on the whole compound command
                    }
                    #endregion

                    message = "Connector move";
                    #endregion
                }
                else
                {
                    #region We are moving entities other than a connector
                    Bundle bundle = new Bundle(Controller.Model);
                    bundle.Entities.AddRange(Selection.SelectedItems);
                    MoveCommand cmd = new MoveCommand(this.Controller, bundle, new Point(lastPoint.X - initialPoint.X, lastPoint.Y - initialPoint.Y));
                    package.Commands.Add(cmd);
                    //not necessary to perform the Redo action of the command since the mouse-move already moved the bundle!
                    #endregion

                    message = "Entities move";
                }
                //reset the hovered connector, if any
                if (hoveredConnector != null)
                {
                    hoveredConnector.Hovered = false;
                }
                package.Text = message;
                //whatever the content of the package we add it to the undo history
                this.Controller.UndoManager.AddUndoCommand(package);

                //show the tracker again
                this.Controller.View.ShowTracker();
            }
        }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
    public void MouseUp(MouseEventArgs e) {
      if (IsActive) {
        // First, make sure the initial point is far enough away from 
        // the final point to make a connection.
        int maxX = Math.Abs(Math.Max(initialPoint.X, e.Location.X));
        int maxY = Math.Abs(Math.Max(initialPoint.Y, e.Location.Y));

        if (!(maxX > ConnectionBase.MinLength) ||
            !(maxY > ConnectionBase.MinLength)) {
          return;
        }

        //whatever comes hereafter, a compund command is the most economic approach
        CompoundCommand package = new CompoundCommand(this.Controller);

        //let's see if the connection endpoints hit other connectors
        //note that the following can be done because the actual connection has not been created yet
        //otherwise the search would find the endpoints of the newly created connection, which
        //would create a loop and a stack overflow!
        IConnector startConnector = this.Controller.Model.Selection.FindConnectorAt(initialPoint);
        IConnector endConnector = this.Controller.Model.Selection.FindConnectorAt(e.Location);

        #region Create the new connection
        Connection cn = new Connection(this.initialPoint, e.Location, this.Controller.Model);
        AddConnectionCommand newcon = new AddConnectionCommand(this.Controller, cn);

        #endregion

        #region Initial attachment?
        if (startConnector != null) {
          BindConnectorsCommand bindStart = new BindConnectorsCommand(this.Controller, startConnector, cn.From);
          package.Commands.Add(bindStart);
        }
        #endregion

        #region Final attachment?
        if (endConnector != null) {
          BindConnectorsCommand bindEnd = new BindConnectorsCommand(this.Controller, endConnector, cn.To);
          package.Commands.Add(bindEnd);
        }
        #endregion
        package.Text = "New connection";
        package.Commands.Add(newcon);
        this.Controller.UndoManager.AddUndoCommand(package);

        //do it all
        package.Redo();

        //reset highlight of the found connector
        if (foundConnector != null)
          foundConnector.Hovered = false;
        //drop the painted ghost
        Controller.View.ResetGhost();
        this.doDraw = false;
      }
    }
        /// <summary>
        ///
        /// </summary>
        /// <param name="e">The <see cref="T:System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        public void MouseUp(MouseEventArgs e)
        {
            if (IsActive)
            {
                // First, make sure the initial point is far enough away from
                // the final point to make a connection.
                int maxX = Math.Abs(Math.Max(initialPoint.X, e.Location.X));
                int maxY = Math.Abs(Math.Max(initialPoint.Y, e.Location.Y));

                if (!(maxX > ConnectionBase.MinLength) ||
                    !(maxY > ConnectionBase.MinLength))
                {
                    return;
                }

                //whatever comes hereafter, a compund command is the most economic approach
                CompoundCommand package = new CompoundCommand(this.Controller);

                //let's see if the connection endpoints hit other connectors
                //note that the following can be done because the actual connection has not been created yet
                //otherwise the search would find the endpoints of the newly created connection, which
                //would create a loop and a stack overflow!
                IConnector startConnector = this.Controller.Model.Selection.FindConnectorAt(initialPoint);
                IConnector endConnector   = this.Controller.Model.Selection.FindConnectorAt(e.Location);

                #region Create the new connection
                Connection           cn     = new Connection(this.initialPoint, e.Location, this.Controller.Model);
                AddConnectionCommand newcon = new AddConnectionCommand(this.Controller, cn);

                #endregion

                #region Initial attachment?
                if (startConnector != null)
                {
                    BindConnectorsCommand bindStart = new BindConnectorsCommand(this.Controller, startConnector, cn.From);
                    package.Commands.Add(bindStart);
                }
                #endregion

                #region Final attachment?
                if (endConnector != null)
                {
                    BindConnectorsCommand bindEnd = new BindConnectorsCommand(this.Controller, endConnector, cn.To);
                    package.Commands.Add(bindEnd);
                }
                #endregion
                package.Text = "New connection";
                package.Commands.Add(newcon);
                this.Controller.UndoManager.AddUndoCommand(package);

                //do it all
                package.Redo();

                //reset highlight of the found connector
                if (foundConnector != null)
                {
                    foundConnector.Hovered = false;
                }
                //drop the painted ghost
                Controller.View.ResetGhost();
                this.doDraw = false;
            }
        }