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