Exemplo n.º 1
0
        /// <summary>
        /// Gets the lineage of this group pin, starting with the group pin, and ending with
        /// the top-level group pin</summary>
        private IEnumerable <GroupPin> GetLineage(bool inputSide)
        {
            GroupPin grpPin  = this;
            DomNode  domNode = DomNode;

            while (grpPin != null)
            {
                yield return(grpPin);

                GroupPin nextGrpPin = null;

                var subGraph = domNode.Parent.Cast <Group>();

                if (subGraph.ParentGraph.Is <Group>())
                {
                    var parentSubGraph = subGraph.ParentGraph.Cast <Group>();

                    if (parentSubGraph != null)
                    {
                        var parentPins = inputSide ? parentSubGraph.InputGroupPins : parentSubGraph.OutputGroupPins;
                        foreach (var parentPin in parentPins)
                        {
                            if (parentPin.InternalElement == subGraph && parentPin.InternalPinIndex == grpPin.Index)
                            {
                                nextGrpPin = parentPin;
                                domNode    = nextGrpPin.DomNode;
                                break;
                            }
                        }
                    }
                }

                grpPin = nextGrpPin;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Performs custom actions after an attribute in the DOM node subtree changed</summary>
        /// <param name="sender">Sender (root DOM node)</param>
        /// <param name="e">Attribute change event args</param>
        protected override void OnAttributeChanged(object sender, AttributeEventArgs e)
        {
            if (Validating && !m_undoingOrRedoing)
            {
                if (e.DomNode.Parent.Is <Group>() && e.AttributeInfo == ElementLabelAttribute)
                {
                    var subGraph = e.DomNode.Parent.Cast <Group>();
                    if (e.DomNode.Is <Element>())
                    {
                        // the name of a sub-node has changed, needs to update group pin names that are not manually set
                        SyncGroupPinNamesFromModuleName(subGraph, e.DomNode);
                    }
                }
                else if (e.DomNode.Is <GroupPin>() && e.AttributeInfo == PinNameAttributeAttribute)
                {
                    if (e.DomNode.Parent != null)
                    {
                        var subGraph = e.DomNode.Parent.Cast <Group>();
                        // ensure group pin names are unique at local level
                        UniqueNamer uniqueName  = new UniqueNamer();
                        GroupPin    childGrpPin = e.DomNode.Cast <GroupPin>();

                        foreach (var grpPin in subGraph.InputGroupPins)
                        {
                            if (grpPin != childGrpPin)
                            {
                                uniqueName.Name((string)grpPin.Name);
                            }
                        }

                        foreach (var grpPin in subGraph.OutputGroupPins)
                        {
                            if (grpPin != childGrpPin)
                            {
                                uniqueName.Name((string)grpPin.Name);
                            }
                        }

                        string unique = uniqueName.Name((string)childGrpPin.Name);
                        if (unique != childGrpPin.Name)
                        {
                            childGrpPin.Name.SetString(unique);
                        }

                        // Reset IsDefaultName. Ignore the suffix because there are typically multiple
                        //  circuit elements in a group and the child group pin doesn't know about
                        //  our unique namer.
                        var    defaultName = childGrpPin.DefaultName(childGrpPin.IsInputSide);
                        string ourRoot;
                        int    ourSuffix;
                        uniqueName.Parse(unique, out ourRoot, out ourSuffix);
                        childGrpPin.IsDefaultName = defaultName == ourRoot;

                        UpdateParentGroupPinName(childGrpPin.IsInputSide, childGrpPin);
                    }
                }
            }

            base.OnAttributeChanged(sender, e);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Performs custom actions after an attribute in the DOM node subtree changed</summary>
        /// <param name="sender">Sender (root DOM node)</param>
        /// <param name="e">Attribute change event args</param>
        protected override void OnAttributeChanged(object sender, AttributeEventArgs e)
        {
            if (Validating && !m_undoingOrRedoing)
            {
                if (e.DomNode.Parent.Is <Group>() && e.AttributeInfo == ElementLabelAttribute)
                {
                    var subGraph = e.DomNode.Parent.Cast <Group>();
                    if (e.DomNode.Is <Element>())
                    {
                        // the name of a sub-node has changed, needs to update group pin names that are not manually set
                        SyncGroupPinNamesFromModuleName(subGraph, e.DomNode);
                    }
                }
                else if (e.DomNode.Is <GroupPin>() && e.AttributeInfo == PinNameAttributeAttribute)
                {
                    if (e.DomNode.Parent != null)
                    {
                        var subGraph = e.DomNode.Parent.Cast <Group>();
                        // ensure group pin names are unique at local level
                        UniqueNamer uniqueName  = new UniqueNamer();
                        GroupPin    childGrpPin = e.DomNode.Cast <GroupPin>();


                        foreach (var pin in subGraph.Inputs)
                        {
                            var grpPin = pin.Cast <GroupPin>();
                            if (grpPin != childGrpPin)
                            {
                                uniqueName.Name(grpPin.Name);
                            }
                        }

                        foreach (var pin in subGraph.Outputs)
                        {
                            var grpPin = pin.Cast <GroupPin>();
                            if (grpPin != childGrpPin)
                            {
                                uniqueName.Name(grpPin.Name);
                            }
                        }


                        string unique = uniqueName.Name(childGrpPin.Name);
                        if (unique != childGrpPin.Name)
                        {
                            childGrpPin.Name = unique;
                        }

                        // try to reset IsDefaultName
                        childGrpPin.IsDefaultName = childGrpPin.Name == childGrpPin.DefaultName(childGrpPin.IsInputSide);
                        UpdateParentGroupPinName(childGrpPin.IsInputSide, childGrpPin);
                    }
                }
            }

            base.OnAttributeChanged(sender, e);
        }
Exemplo n.º 4
0
        // whether freePin's desired location overlaps static pin's actual location
        private static bool PinOverlap(GroupPin freePin, GroupPin againstPin)
        {
            // consider a pin's y interval is  (pinY - PinNodeMargin,  pinY +  PinNodeHeight +PinNodeMargin) top down
            // freePin overlaps againstPin if the two intervals overlap
            var freePinInterval = new Pair <int, int>(freePin.DesiredLocation.Y - CircuitGroupPinInfo.FloatingPinNodeMargin, freePin.DesiredLocation.Y + CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin);
            var pinInterval     = new Pair <int, int>(againstPin.Bounds.Location.Y - CircuitGroupPinInfo.FloatingPinNodeMargin, againstPin.Bounds.Location.Y + CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin);

            // two intervals i1 = (s1, e1) and i2 = (s2, e2) overlap if and only if s2 < e1 and s1 < e2
            return((pinInterval.First < freePinInterval.Second) && // s2 < e1
                   (freePinInterval.First < pinInterval.Second));  //s1 < e2
        }
Exemplo n.º 5
0
        /// <summary>
        /// Propagate up group pin name changes to the parent pin (only need to take care of non-default name,
        /// the default names are auto-updated in Group.UpdateGroupPins())</summary>
        private void UpdateParentGroupPinName(bool inputSide, GroupPin childPin)
        {
            var parentGrpPin = childPin.GetAncestry(inputSide).FirstOrDefault();

            if (parentGrpPin != null)
            {
                if (!childPin.IsDefaultName && parentGrpPin.IsDefaultName)
                {
                    parentGrpPin.Name          = childPin.Name;
                    parentGrpPin.IsDefaultName = false;
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Resolve pin node position to avoid colliding with any node in againstPinNodes</summary>
        /// <param name="againstPinNodes">List of GroupPins to avoid collision with</param>
        /// <param name="floatingPin">Floating pin to adjust: use its DesiredLocation to check collisions and its ActualLocation will be set upon return</param>
        /// <param name="minY">Minimum Y value the floating pin is allowed to take</param>
        private void PositioningFloatigPin(IList <GroupPin> againstPinNodes, GroupPin floatingPin, int minY)
        {
            // resolve pin node position to avoid colliding with any against-pins
            bool overlapped = false;

            for (int p = 0; p < againstPinNodes.Count; ++p) // try to locate sufficient empty space between the static nodes
            {
                var againstpin = againstPinNodes[p];
                if (againstpin.Bounds.Location.Y + CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin < minY)
                {
                    continue;
                }
                if (PinOverlap(floatingPin, againstpin))
                {
                    overlapped = true;
                    // find next suitable place from p down (note againstPinNodes y-ascending order, i.e. higher notes appear first)
                    for (int j = p; j < againstPinNodes.Count - 1; ++j)
                    {
                        if (againstPinNodes[j + 1].Bounds.Location.Y - againstPinNodes[j].Bounds.Location.Y >= 2 * (CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin))
                        {
                            // find empty space >=  pin node height + margin
                            // place the floating pin just above static pin j
                            int pinNewY = Constrain(againstPinNodes[j].Bounds.Location.Y + CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin);
                            floatingPin.Bounds = new Rectangle(floatingPin.Bounds.Location.X, pinNewY, floatingPin.Bounds.Width, floatingPin.Bounds.Height);
                            return;
                        }
                    }
                }
            }

            if (overlapped) // no in-between empty space to insert, try at the top region first, then the bottom region
            {
                // top region
                var topStaticPin = againstPinNodes[0];
                int pinNewY      = Constrain(topStaticPin.Bounds.Location.Y - (CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin));
                pinNewY = Math.Max(pinNewY, minY);
                floatingPin.DesiredLocation = new Point(floatingPin.DesiredLocation.X, pinNewY);
                if (pinNewY > minY && !PinOverlap(floatingPin, topStaticPin))
                {
                    floatingPin.Bounds = new Rectangle(floatingPin.Bounds.Location.X, pinNewY, floatingPin.Bounds.Width,
                                                       floatingPin.Bounds.Height);
                }
                else // bottom region
                {
                    var bottomStaticPin = againstPinNodes[againstPinNodes.Count - 1];
                    pinNewY =
                        Constrain(bottomStaticPin.Bounds.Location.Y +
                                  (CircuitGroupPinInfo.FloatingPinNodeHeight + CircuitGroupPinInfo.FloatingPinNodeMargin));
                    pinNewY = Math.Max(pinNewY, minY);
                    floatingPin.DesiredLocation = new Point(floatingPin.DesiredLocation.X, pinNewY);
                    const int increment = 1;
                    while (PinOverlap(floatingPin, bottomStaticPin))
                    {
                        pinNewY += increment;
                        floatingPin.DesiredLocation = new Point(floatingPin.DesiredLocation.X, pinNewY);
                    }

                    floatingPin.Bounds = new Rectangle(floatingPin.Bounds.Location.X, pinNewY, floatingPin.Bounds.Width,
                                                       floatingPin.Bounds.Height);
                }
            }
            else // the disired location turns out just fine
            {
                floatingPin.Bounds = new Rectangle(floatingPin.Bounds.Location.X, Constrain(floatingPin.DesiredLocation.Y), floatingPin.Bounds.Width, floatingPin.Bounds.Height);
            }
        }