/// 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); }
/// <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; } }
/// <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; } }