示例#1
0
        /// <summary>
        /// Moves the given nodes into a container</summary>
        /// <param name="newParent">New container</param>
        /// <param name="movingObjects">Nodes to move</param>
        void IEditableGraphContainer <Element, Wire, ICircuitPin> .Move(object newParent, IEnumerable <object> movingObjects)
        {
            if (newParent == null)
            {
                newParent = this;
            }

            var movingItems = movingObjects.ToArray();

            var moduleSet    = new HashSet <Element>();
            var movingNodes  = movingItems.AsIEnumerable <Element>().ToArray();
            var newContainer = newParent.Cast <ICircuitContainer>();
            var oldContainer = movingNodes.First().DomNode.Parent.Cast <ICircuitContainer>();

            Debug.Assert(oldContainer != newContainer);


            // all relevant (internal to the old container) edges before the moving
            var internalConnections = new List <Wire>();
            var incomingConnections = new List <Wire>();
            var outgoingConnections = new List <Wire>();

            CircuitUtil.GetSubGraph(oldContainer, movingItems, moduleSet, internalConnections, incomingConnections, outgoingConnections);
            var graphValidator = DomNode.GetRoot().Cast <CircuitValidator>();

            graphValidator.Suspended = true;

            // transfer modules
            foreach (var module in movingNodes)
            {
                oldContainer.Elements.Remove(module);
                newContainer.Elements.Add(module);
            }

            // transfer internal connections (those between grouped modules)
            foreach (Wire connection in internalConnections)
            {
                oldContainer.Wires.Remove(connection);
                newContainer.Wires.Add(connection);
            }

            // locaton transformation of moved modules
            var offset = GetRelativeOffset(oldContainer, newContainer);

            foreach (var module in movingNodes)
            {
                var relLoc = module.Bounds.Location;
                relLoc.Offset(offset);
                module.Bounds = new Rectangle(relLoc, module.Bounds.Size);
            }

            graphValidator.Suspended            = false;
            graphValidator.MovingCrossContainer = true;
        }
示例#2
0
        /// <summary>
        /// Populates a newly created group with circuit elements that are currently in the given graph</summary>
        /// <param name="newGroup">A new group, empty of circuit elements</param>
        /// <param name="elementsToGroup">The circuit elements to move into 'newGroup'.</param>
        /// <param name="graphContainer">The container for the circuit elements and their wires. These will
        /// be removed from 'graphContainer' and placed into 'newGroup'.</param>
        /// <remarks>This method is intended to help with persistence of circuit groups.</remarks>
        public static void CreateGroup(Group newGroup, IEnumerable <object> elementsToGroup, ICircuitContainer graphContainer)
        {
            // get the selected modules and the connections between them
            HashSet <Element> modules             = new HashSet <Element>();
            List <Wire>       internalConnections = new List <Wire>();
            List <Wire>       externalConnections = new List <Wire>();

            CircuitUtil.GetSubGraph(graphContainer, elementsToGroup, modules, internalConnections, externalConnections, externalConnections);

            // the group must be added before transferring modules and connections to it,
            //  so that the history mechanism will capture all the changes.
            graphContainer.Elements.Add(newGroup);

            // transfer modules
            foreach (Element module in modules)
            {
                graphContainer.Elements.Remove(module);
                newGroup.Elements.Add(module);
            }

            // auto-generate sub-graph group pins to support the external connections to group
            // group pins may have multiple external connections
            newGroup.UpdateGroupPins(modules, internalConnections, externalConnections);

            // transfer internal connections (those between grouped modules)
            foreach (Wire connection in internalConnections)
            {
                graphContainer.Wires.Remove(connection);
                newGroup.Wires.Add(connection);
            }

            // initalize group pin's index and pinY
            newGroup.InitializeGroupPinIndexes(internalConnections);

            if (graphContainer.Is <Group>()) // making a group inside a group
            {
                // remap group pins in the parent group
                var parentGroup = graphContainer.Cast <Group>();

                // remap parent group pins that reference the new group's subnodes to the new group
                foreach (var grpPin in parentGroup.InputGroupPins)
                {
                    if (modules.Contains(grpPin.InternalElement))
                    {
                        // adjust the internal pin index first
                        for (int j = 0; j < newGroup.Inputs.Count; ++j)
                        {
                            var newGrpPin = newGroup.Inputs[j] as GroupPin;
                            if (newGrpPin.InternalElement.DomNode == grpPin.InternalElement.DomNode &&
                                newGrpPin.InternalPinIndex == grpPin.InternalPinIndex)
                            {
                                grpPin.InternalPinIndex = j;
                                newGrpPin.Name          = grpPin.Name;
                                //grpPin.Name = newGroup.Name + ":" + newGrpPin.Name;

                                break;
                            }
                        }
                        // now update node references for the parent group pin
                        grpPin.InternalElement = newGroup;
                    }
                }

                foreach (var grpPin in parentGroup.OutputGroupPins)
                {
                    if (modules.Contains(grpPin.InternalElement))
                    {
                        // adjust the internal pin index first
                        for (int j = 0; j < newGroup.Outputs.Count; ++j)
                        {
                            var newGrpPin = newGroup.Outputs[j] as GroupPin;
                            if (newGrpPin.InternalElement.DomNode == grpPin.InternalElement.DomNode &&
                                newGrpPin.InternalPinIndex == grpPin.InternalPinIndex)
                            {
                                grpPin.InternalPinIndex = j;
                                newGrpPin.Name          = grpPin.Name;
                                //grpPin.Name = newGroup.Name + ":" + newGrpPin.Name;

                                break;
                            }
                        }
                        // now update node references for the parent group pin
                        grpPin.InternalElement = newGroup;
                    }
                }
            }

            newGroup.OnChanged(EventArgs.Empty); // notify the change( derived class of Group may need custom actions)

            // Remap external connections from grouped modules to group.
            foreach (Wire connection in externalConnections)
            {
                var groupInputPin = newGroup.MatchedGroupPin(connection.InputElement, connection.InputPin.Index, true);
                if (groupInputPin != null)
                {
                    groupInputPin.SetPinTarget(true);

                    // reroute original edge
                    connection.SetInput(newGroup, groupInputPin);
                    connection.InputPinTarget = groupInputPin.PinTarget;
                }

                var groupOutputPin = newGroup.MatchedGroupPin(connection.OutputElement, connection.OutputPin.Index, false);
                if (groupOutputPin != null)
                {
                    groupOutputPin.SetPinTarget(false);

                    // reroute original edge
                    connection.SetOutput(newGroup, groupOutputPin);
                    connection.OutputPinTarget = groupOutputPin.PinTarget;
                }
            }


            // find upper-left corner of the subnodes
            Point minLocation = new Point(int.MaxValue, int.MaxValue);

            foreach (var module in newGroup.Elements)
            {
                if (minLocation.X > module.Bounds.Location.X)
                {
                    minLocation.X = module.Bounds.Location.X;
                }
                if (minLocation.Y > module.Bounds.Location.Y)
                {
                    minLocation.Y = module.Bounds.Location.Y;
                }
            }
            // offset sub-nodes location so they are relative to the parent
            foreach (var module in newGroup.Elements)
            {
                var relLoc = module.Bounds.Location;
                relLoc.Offset(-minLocation.X, -minLocation.Y);
                module.Bounds   = new Rectangle(relLoc, module.Bounds.Size);
                module.Position = module.Bounds.Location;
            }
        }