예제 #1
0
        /// <summary>
        /// Returns a list of all modules, internal connections between them, and connections
        /// to external modules</summary>
        /// <param name="graphContainer">Circuit container</param>
        /// <param name="objects">Enumeration of all selected objects, edges possible</param>
        /// <param name="modules">Modules in selected objects, filled by method</param>
        /// <param name="internalConnections">Collection of all internal connections, filled by method</param>
        /// <param name="incomingConnections">Collection of all incoming connections, filled by method</param>
        /// <param name="outgoingConnections">Collection of all outgoing connections, filled by method</param>
        public static void GetSubGraph(
            ICircuitContainer graphContainer,
            IEnumerable <object> objects, // [in] selected objects, edges possible
            HashSet <Element> modules,    // [out] elements in the selected objects
            ICollection <Wire> internalConnections,
            ICollection <Wire> incomingConnections,
            ICollection <Wire> outgoingConnections)
        {
            // build the set of modules, and add them to result
            foreach (var module in objects.AsIEnumerable <Element>())
            {
                modules.Add(module);
            }

            // add connections to modules
            foreach (var connection in graphContainer.Wires)
            {
                bool output = modules.Contains(connection.OutputElement);
                bool input  = modules.Contains(connection.InputElement);
                if (output && input)
                {
                    internalConnections.Add(connection);
                }
                else if (output)
                {
                    outgoingConnections.Add(connection);
                }
                else if (input)
                {
                    incomingConnections.Add(connection);
                }
            }
        }
예제 #2
0
        // returns a list of all modules, internal connections between them, and connections
        //  to external modules
        private static void GetSubCircuit(
            IEnumerable <object> objects,
            ICircuitContainer circuit,
            HashSet <Element> modules,
            ICollection <Wire> connections,
            ICollection <Wire> internalConnections,
            ICollection <Wire> externalConnections)
        {
            // build the set of modules, and add them to result
            foreach (Element module in Adapters.AsIEnumerable <Element>(objects))
            {
                modules.Add(module);
            }

            // add connections to modules
            foreach (Wire connection in circuit.Wires)
            {
                bool output = modules.Contains(connection.OutputElement);
                bool input  = modules.Contains(connection.InputElement);
                if (output && input)
                {
                    connections.Add(connection);
                }
                else if (output)
                {
                    externalConnections.Add(connection);
                }
                else if (input)
                {
                    internalConnections.Add(connection);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Ungroups the given group, causing its child elements to be moved to the given container</summary>
        /// <param name="group">The group to destroy while preserving its child elements</param>
        /// <param name="circuitContainer">The container that currently holds the group</param>
        /// <remarks>This method is intended to help with persistence of circuit groups.</remarks>
        public static void UngroupGroup(Group group, ICircuitContainer circuitContainer)
        {
            // restore external connections to modules in group
            foreach (Wire connection in circuitContainer.Wires)
            {
                if (connection.InputElement.As <Group>() == group)
                {
                    var     pin     = connection.InputPin.As <GroupPin>();
                    Element element = pin.InternalElement;
                    connection.SetInput(element, element.Type.Inputs[pin.InternalPinIndex]);
                }
                else if (connection.OutputElement.As <Group>() == group)
                {
                    var     pin     = connection.OutputPin.As <GroupPin>();
                    Element element = pin.InternalElement;
                    connection.SetOutput(element, element.Type.Outputs[pin.InternalPinIndex]);
                }
            }

            // restore modules
            IList <Element> modules = group.Elements;

            for (int i = modules.Count - 1; i >= 0; i--)
            {
                Element element = modules[i];
                modules.RemoveAt(i);
                // location restores to parent space
                element.Bounds = new Rectangle(element.Bounds.Location.X + group.Bounds.Location.X - group.Info.Offset.X,
                                               element.Bounds.Location.Y + group.Bounds.Location.Y - group.Info.Offset.Y,
                                               element.Bounds.Width, element.Bounds.Height);

                circuitContainer.Elements.Add(element);
            }

            // restore internal connections
            IList <Wire> connections = group.Wires;

            for (int i = connections.Count - 1; i >= 0; i--)
            {
                Wire wire = connections[i];
                connections.RemoveAt(i);
                circuitContainer.Wires.Add(wire);
            }

            // remove group
            circuitContainer.Elements.Remove(group);
        }
예제 #4
0
        /// Gets location offset from oldContainer to newContainer, compensate renderer displacements for element title
        /// and margin sub-nodes location are defined relative to the parent container
        private Point GetRelativeOffset(ICircuitContainer oldContainer, ICircuitContainer newContainer)
        {
            AdaptableControl control = m_viewingContext.Cast <AdaptableControl>();

            var offset          = new Point();
            var oldDomContainer = oldContainer.Cast <DomNode>();
            var newDomContainer = newContainer.Cast <DomNode>();

            var commonAncestor = DomNode.GetLowestCommonAncestor(oldDomContainer, newDomContainer);

            var upPath   = oldDomContainer.Lineage.TakeWhile(x => x != commonAncestor);
            var upOffset = GetWorldOffset(control, upPath.AsIEnumerable <Element>());

            offset.Offset(upOffset.X, upOffset.Y);

            var downPath   = newDomContainer.Lineage.TakeWhile(x => x != commonAncestor).Reverse();
            var downOffset = GetWorldOffset(control, downPath.AsIEnumerable <Element>());

            offset.Offset(-downOffset.X, -downOffset.Y);
            return(offset);
        }
예제 #5
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;
            }
        }
예제 #6
0
        // returns a list of all modules, internal connections between them, and connections
        //  to external modules
        private static void GetSubCircuit(
            IEnumerable<object> objects,
            ICircuitContainer circuit,
            HashSet<Element> modules,
            ICollection<Wire> connections,
            ICollection<Wire> internalConnections,
            ICollection<Wire> externalConnections)
        {
            // build the set of modules, and add them to result
            foreach (Element module in Adapters.AsIEnumerable<Element>(objects))
                modules.Add(module);

            // add connections to modules
            foreach (Wire connection in circuit.Wires)
            {
                bool output = modules.Contains(connection.OutputElement);
                bool input = modules.Contains(connection.InputElement);
                if (output && input)
                {
                    connections.Add(connection);
                }
                else if (output)
                {
                    externalConnections.Add(connection);
                }
                else if (input)
                {
                    internalConnections.Add(connection);
                }
            }
        }
예제 #7
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);
            }

            // initialize 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 
                        foreach (var newGrpPin in newGroup.InputGroupPins)
                        {
                            if (newGrpPin.InternalElement.DomNode == grpPin.InternalElement.DomNode &&
                                newGrpPin.InternalPinIndex == grpPin.InternalPinIndex)
                            {
                                grpPin.InternalPinIndex = newGrpPin.Index;
                                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 
                        foreach (var newGrpPin in newGroup.OutputGroupPins)
                        {
                            if (newGrpPin.InternalElement.DomNode == grpPin.InternalElement.DomNode &&
                                newGrpPin.InternalPinIndex == grpPin.InternalPinIndex)
                            {
                                grpPin.InternalPinIndex = newGrpPin.Index;
                                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;
            }
        }
예제 #8
0
        /// <summary>
        /// Ungroups the given group, causing its child elements to be moved to the given container</summary>
        /// <param name="group">The group to destroy while preserving its child elements</param>
        /// <param name="circuitContainer">The container that currently holds the group</param>
        /// <remarks>This method is intended to help with persistence of circuit groups.</remarks>
        public static void UngroupGroup(Group group, ICircuitContainer circuitContainer)
        {
            // restore external connections to modules in group
            foreach (Wire connection in circuitContainer.Wires)
            {
                if (connection.InputElement.As<Group>() == group)
                {
                    var pin = connection.InputPin.As<GroupPin>();
                    Element element = pin.InternalElement;
                    connection.SetInput(element, element.InputPin(pin.InternalPinIndex));
                }
                else if (connection.OutputElement.As<Group>() == group)
                {
                    var pin = connection.OutputPin.As<GroupPin>();
                    Element element = pin.InternalElement;
                    connection.SetOutput(element, element.OutputPin(pin.InternalPinIndex));
                }
            }

            // restore modules
            IList<Element> modules = group.Elements;
            for (int i = modules.Count - 1; i >= 0; i--)
            {
                Element element = modules[i];
                modules.RemoveAt(i);
                // location restores to parent space
                element.Bounds = new Rectangle(element.Bounds.Location.X + group.Bounds.Location.X - group.Info.Offset.X,
                                              element.Bounds.Location.Y + group.Bounds.Location.Y - group.Info.Offset.Y,
                                              element.Bounds.Width, element.Bounds.Height);

                circuitContainer.Elements.Add(element);
            }

            // restore internal connections
            IList<Wire> connections = group.Wires;
            for (int i = connections.Count - 1; i >= 0; i--)
            {
                Wire wire = connections[i];
                connections.RemoveAt(i);
                circuitContainer.Wires.Add(wire);
            }

            // remove group
            circuitContainer.Elements.Remove(group);           
        }