/// <summary>
        /// Called by the ComponentTerminalShape bounds rule.
        /// </summary>
        /// <param name="terminal"></param>
        /// <returns></returns>
        public override PointD GetTerminalLocation(ComponentTerminal terminal)
        {
            Capacitor capacitor = ModelElement as Capacitor;

            if (capacitor == null)
            {
                return(new PointD(0, 0));
            }

            if (AbsoluteBounds.Height < AbsoluteBounds.Width)
            {
                if ((capacitor.T1 == terminal) == ((rotate + 1) % 4 < 2))
                {
                    return(ScalePoint(0.5, 0));
                }
                else
                {
                    return(ScalePoint(0.5, 1));
                }
            }
            else
            {
                if ((capacitor.T1 == terminal) == ((rotate + 1) % 4 < 2))
                {
                    return(ScalePoint(0, 0.5));
                }
                else
                {
                    return(ScalePoint(1, 0.5));
                }
            }
        }
        /// <summary>
        /// Called when the user or program code tries to move or resize the shape, and when the shape is initially created.
        /// In this case, we restrict the ComponentTerminal to be at a fixed position on the shape, with a fixed size.
        /// </summary>
        /// <param name="shape">The shape that is being moved or created.</param>
        /// <param name="proposedBounds">What the user or code would like.</param>
        /// <returns>The permitted bounds that are closest to the proposedBounds.</returns>
        public override RectangleD GetCompliantBounds(ShapeElement shape, RectangleD proposedBounds)
        {
            ComponentTerminal terminal = shape.ModelElement as ComponentTerminal;

            if (terminal == null)
            {
                return(proposedBounds);
            }
            ComponentTerminalShape terminalShape  = shape as ComponentTerminalShape;
            ComponentShape         componentShape = terminalShape.ParentShape as ComponentShape;

            if (componentShape == null)
            {
                return(proposedBounds);
            }

            // Location depends on which terminal it is, of which type of shape.
            PointD relativeLocation = componentShape.GetTerminalLocation(terminal);

            if (relativeLocation.X > 0 || relativeLocation.Y > 0)
            {
                return(new RectangleD(relativeLocation.X - 0.025, relativeLocation.Y - 0.025, proposedBounds.Width, proposedBounds.Height));
            }
            else
            {
                return(proposedBounds);
            }
        }
        /* There are two versions of CreateElementToolPrototype here.
         * One deals with each Component subtype separately: if you add a new subtype, you need to add more here.
         * The other automatically deals with eacn Component subtype, using DSL reflection info.
         *
         * See http://msdn.microsoft.com/library/bb126279.aspx#groups
         */

        /*
         * /// <summary>
         * /// Toolbox initialization, called for each element tool on the toolbox.
         * /// This version deals with each Component subtype separately.
         * /// </summary>
         * /// <param name="store"></param>
         * /// <param name="domainClassId">Identifies the domain class this tool should instantiate.</param>
         * /// <returns>prototype of the object or group of objects to be created by tool</returns>
         * protected override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId)
         * {
         *
         *  if (domainClassId == Resistor.DomainClassId)
         *  {
         *      Resistor resistor = new Resistor(store);
         *
         *      // Must initialize these in order of initialization:
         *      // DSLT v1 bug affecting derived relationships.
         *      resistor.T1 = new ComponentTerminal(store);
         *      resistor.T2 = new ComponentTerminal(store);
         *
         *      resistor.T1.Name = "t1";
         *      resistor.T2.Name = "t2";
         *
         *      ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
         *      elementGroup.AddGraph(resistor, true);
         *      // AddGraph includes the embedded parts.
         *
         *      return elementGroup.CreatePrototype();
         *  }
         *  else if (domainClassId == Capacitor.DomainClassId)
         *  {
         *      Capacitor capacitor = new Capacitor(store);
         *
         *      // Must initialize these in order of initialization:
         *      // DSLT v1 bug affecting derived relationships.
         *      capacitor.T1 = new ComponentTerminal(store);
         *      capacitor.T2 = new ComponentTerminal(store);
         *
         *      capacitor.T1.Name = "t1";
         *      capacitor.T2.Name = "t2";
         *
         *      ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
         *      elementGroup.AddGraph(capacitor, true);
         *      // AddGraph includes the embedded parts.
         *
         *      return elementGroup.CreatePrototype();
         *  }
         *
         *  else if (domainClassId == Transistor.DomainClassId)
         *  {
         *      Transistor transistor = new Transistor(store);
         *
         *      // Must initialize these in order of initialization:
         *      // DSLT v1 bug affecting derived relationships.
         *      transistor.Base = new ComponentTerminal(store);
         *      transistor.Collector = new ComponentTerminal(store);
         *      transistor.Emitter = new ComponentTerminal(store);
         *
         *      transistor.Base.Name = "base";
         *      transistor.Collector.Name = "collector";
         *      transistor.Emitter.Name = "emitter";
         *
         *      // Create an ElementGroup for the Toolbox.
         *      ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
         *      elementGroup.AddGraph(transistor, true);
         *      // AddGraph includes the embedded parts
         *
         *      return elementGroup.CreatePrototype();
         *  }
         *
         *  else
         *  {
         *      return base.CreateElementToolPrototype(store, domainClassId);
         *  }
         *
         *
         * }
         *
         */

        /// <summary>
        /// Toolbox initialization for components with fixed embedded parts.
        /// This deals with all the subclasses of Component, adding an instance for each relationship derived from ComponentHasTerminals.
        /// The benefit of this approach is that it does not need to be adjusted for each new Component subclass.
        /// Called for each element tool on the toolbox.
        /// </summary>
        /// <param name="store"></param>
        /// <param name="domainClassId">Identifies the domain class this tool should instantiate.</param>
        /// <returns>prototype of the object or group of objects to be created by tool</returns>
        protected override ElementGroupPrototype CreateElementToolPrototype(Store store, Guid domainClassId)
        {
            // Called for each element tool on the toolbox.
            // Get the class meta info for this class.
            DomainClassInfo thisClassInfo = store.DomainDataDirectory.FindDomainClass(domainClassId);

            if (!thisClassInfo.IsDerivedFrom(Component.DomainClassId))
            {
                // Not one of those we're interested in: defer to base method.
                return(base.CreateElementToolPrototype(store, domainClassId));
            }
            else
            {
                // Construct an instance of this type. Use the constructor that takes a store and a variable number of property bindings.
                Component component = (Component)thisClassInfo.ImplementationClass. // get the actual class from the meta info
                                      InvokeMember(                                 // method in System.Reflection.Type
                    "",
                    System.Reflection.BindingFlags.CreateInstance                   // invoke the constructor
                    | System.Reflection.BindingFlags.OptionalParamBinding,          // which has a params binding
                    null,                                                           // no special binder
                    null,                                                           //no target object since we want the constructor
                    new object[] { store });                                        // Called like "new Resistor(store)"

                // Now add whatever ComponentTerminals it has.
                // Each Component subtype sources several subrelationships of ComponentHasComponentTerminal.
                // Go through the metainfo about each role the class plays in relationships.
                foreach (DomainRoleInfo role in thisClassInfo.LocalDomainRolesPlayed)
                {
                    // Pick out the roles that are one end of a relationship to a Terminal.
                    if (role.DomainRelationship.IsDerivedFrom(ComponentHasComponentTerminal.DomainClassId) &&
                        !role.DomainRelationship.ImplementationClass.IsAbstract)
                    {
                        ComponentTerminal terminal = new ComponentTerminal(store);
                        // Fill in the instance name with the name of the role - just a convenience.
                        // The role at the Terminal end of the relationship is the one called "T1" or "collector" or some such.
                        terminal.Name = role.OppositeDomainRole.Name.ToLowerInvariant();
                        // Instantiate the relationship with the constructor that takes the component and terminal.
                        role.DomainRelationship.ImplementationClass.InvokeMember("", System.Reflection.BindingFlags.CreateInstance,
                                                                                 null, null,
                                                                                 new object[] { component, terminal });
                    }
                }
                // Create an Element Group Prototype containing this tree.
                ElementGroup elementGroup = new ElementGroup(store.DefaultPartition);
                elementGroup.AddGraph(component, true, true); // AddGraph includes the embedded elements.
                elementGroup.AddRange(component.ComponentTerminals, true);
                ElementGroupPrototype egp = elementGroup.CreatePrototype();
                return(egp);
            }
        }
Esempio n. 4
0
        /// <summary>
        /// Called when the user selects an item on the diagram.
        /// Returns the shape that should actually be selected.
        /// </summary>
        /// <param name="currentSelection">The pre-existing selection.</param>
        /// <param name="proposedItemsToAdd">The items that will be selected. Modify this to select something else.</param>
        /// <param name="proposedItemsToRemove">Items that will be removed from the current selection.</param>
        /// <param name="primaryItem">The most recent item selected.</param>
        /// <returns>True if the selection was at least partially successful.</returns>
        public override bool GetCompliantSelection(SelectedShapesCollection currentSelection, DiagramItemCollection proposedItemsToAdd, DiagramItemCollection proposedItemsToRemove, DiagramItem primaryItem)
        {
            // We will modify proposedItemsToAdd, replacing component terminal shapes by component shapes.
            List <DiagramItem> toAdd  = new List <DiagramItem>();
            List <DiagramItem> toDrop = new List <DiagramItem>();

            foreach (DiagramItem item in proposedItemsToAdd)
            {
                if (item.Shape is ComponentTerminalShape)
                {
                    ComponentTerminal terminal = item.Shape.ModelElement as ComponentTerminal;
                    if (terminal == null)
                    {
                        continue;
                    }
                    toAdd.Add(new DiagramItem(item.Diagram.FindShape(terminal.Component)));
                    toDrop.Add(item);
                }
            }
            proposedItemsToAdd.Remove(toDrop); // Remove the terminals.
            proposedItemsToAdd.Add(toAdd);     // Add the parent components.

            return(base.GetCompliantSelection(currentSelection, proposedItemsToAdd, proposedItemsToRemove, primaryItem));
        }
        /// <summary>
        /// A transistor has three terminals: Base, Collector, Emitter.
        /// The location depends on the state of rotation and reflection in RotateFlip.
        /// </summary>
        /// <param name="terminal"></param>
        /// <returns></returns>
        public override PointD GetTerminalLocation(ComponentTerminal terminal)
        {
            Transistor transistor = this.ModelElement as Transistor;

            if (transistor == null)
            {
                return(new PointD(0, 0));
            }
            if (terminal == transistor.Base)
            {
                // Base is half way up the side, in the 0 orientation.
                switch (RotateFlip)
                {
                case 0:
                case 6: return(ScalePoint(0, 0.5));

                case 2:
                case 4: return(ScalePoint(1, 0.5));

                case 1:
                case 7: return(ScalePoint(0.5, 1));

                case 3:
                case 5: return(ScalePoint(0.5, 0));
                }
            }
            const double ceOffset = 0.55;

            if (terminal == transistor.Collector)
            {
                // Collector is at top right, in 0 orientation.
                switch (RotateFlip)
                {
                case 0: return(ScalePoint(ceOffset, 0));

                case 1: return(ScalePoint(0, 1 - ceOffset));

                case 2: return(ScalePoint(1 - ceOffset, 1));

                case 3: return(ScalePoint(1, ceOffset));

                case 4: return(ScalePoint(1 - ceOffset, 0));

                case 5: return(ScalePoint(0, ceOffset));

                case 6: return(ScalePoint(ceOffset, 1));

                case 7: return(ScalePoint(1, 1 - ceOffset));
                }
            }
            if (terminal == transistor.Emitter)
            {
                // Emitter is at bottom right, in 0 orientation.
                switch (RotateFlip)
                {
                case 0: return(ScalePoint(ceOffset, 1));

                case 1: return(ScalePoint(1, 1 - ceOffset));

                case 2: return(ScalePoint(1 - ceOffset, 0));

                case 3: return(ScalePoint(0, ceOffset));

                case 4: return(ScalePoint(1 - ceOffset, 1));

                case 5: return(ScalePoint(1, ceOffset));

                case 6: return(ScalePoint(ceOffset, 0));

                case 7: return(ScalePoint(0, 1 - ceOffset));
                }
            }
            return(new PointD(0, 0));
        }
 public virtual PointD GetTerminalLocation(ComponentTerminal terminal)
 {
     return(new PointD(0, 0));
 }