Exemple #1
0
        /// <summary>
        /// Connect two connections together.  This is the connection on the superior block.
        /// </summary>
        /// <param name="childConnection"></param>
        private void ConnectInternal(Connection childConnection)
        {
            var parentConnection = this;
            var parentBlock      = parentConnection.SourceBlock;
            var childBlock       = childConnection.SourceBlock;

            // Disconnect any existing parent on the child connection.
            if (childConnection.IsConnected)
            {
                childConnection.Disconnect();
            }

            // Other connection is already connected to something.
            // Disconnect it and reattach it or bump it as needed.
            if (parentConnection.IsConnected)
            {
                Block   orphanBlock = parentConnection.TargetBlock;
                XmlNode shadowDom   = parentConnection.ShadowDom;
                parentConnection.ShadowDom = null;

                if (orphanBlock.IsShadow)
                {
                    // Save the shadow block so that field values are preserved.
                    shadowDom = Xml.BlockToDom(orphanBlock);
                    orphanBlock.Dispose();
                    orphanBlock = null;
                }
                else if (parentConnection.Type == Define.EConnection.InputValue)
                {
                    //value connnections
                    if (orphanBlock.OutputConnection == null)
                    {
                        throw new Exception("Orphan block does not have an output connection.");
                    }

                    // Attempt to reattach the orphan at the end of the newly inserted
                    // block.  Since this block may be a row, walk down to the end
                    // or to the first (and only) shadow block.
                    var connection = Connection.LastConnectionInRow(childBlock, orphanBlock);
                    if (connection != null)
                    {
                        orphanBlock.OutputConnection.Connect(connection);
                        orphanBlock = null;
                    }
                }
                else if (parentConnection.Type == Define.EConnection.NextStatement)
                {
                    // Statement connections.
                    // Statement blocks may be inserted into the middle of a stack.
                    // Split the stack.
                    if (orphanBlock.PreviousConnection == null)
                    {
                        throw new Exception("Orphan block does not have a previous connection.");
                    }

                    // Attempt to reattach the orphan at the bottom of the newly inserted
                    // block.  Since this block may be a stack, walk down to the end.
                    var newBlock = childBlock;
                    while (newBlock.NextConnection != null)
                    {
                        var nextBlock = newBlock.NextBlock;
                        if (nextBlock != null && !nextBlock.IsShadow)
                        {
                            newBlock = nextBlock;
                        }
                        else
                        {
                            if (orphanBlock.PreviousConnection.CheckType(newBlock.NextConnection))
                            {
                                newBlock.NextConnection.Connect(orphanBlock.PreviousConnection);
                                orphanBlock = null;
                            }
                            break;
                        }
                    }
                }

                if (orphanBlock != null)
                {
                    // Unable to reattach orphan.
                    parentConnection.Disconnect();
                    Connection orphanBlockCon = orphanBlock.OutputConnection != null ? orphanBlock.OutputConnection : orphanBlock.PreviousConnection;
                    orphanBlockCon.FireUpdate(UpdateState.BumpedAway);
                }

                // Restore the shadow DOM.
                parentConnection.ShadowDom = shadowDom;
            }

            // Establish the connections.
            Connection.ConnectReciprocally(parentConnection, childConnection);
            // Demote the inferior block so that one is a child of the superior one.
            childBlock.SetParent(parentBlock);

            FireUpdate(UpdateState.Connected);
        }