/// <summary> /// Called on copy, cut or drag. /// For a copy or cut, the supplied elements are the model elements, and the call comes, via AddGroupFormat, from ClipboardCommands.ProcessOnMenuCopy(). /// For a drag operation, the elements are the selected shapes and connectors, and the call comes from Diagram.DoDragDrop, if CanMove or CanCopy are true. /// In the drag case, we want to add the model elements so that we can do a copy /// if the user presses CTRL while dragging. /// /// See http://msdn.microsoft.com/library/ff521398.aspx /// </summary> /// <param name="shapeOrModelElements">The shape or model elements being copied - usually the current selection.</param> /// <param name="closureType">Copy or Delete</param> /// <returns>Group to be stored in the clipboard.</returns> protected override ElementGroup CreateElementGroup(ICollection <ModelElement> shapeOrModelElements, ClosureType closureType) { // CreateElementGroup respects the settings of PropagateCopy. // Notice that we have set PropagateCopy on the roles from components to the terminals, // so that terminals will always be copied along with their parents. // Add the specified group of shapes or elements: ElementGroup group = base.CreateElementGroup(shapeOrModelElements, closureType); // If this a set of shapes, add their model elements: if (shapeOrModelElements.FirstOrDefault() is PresentationElement) { // Get the model elements of the shapes: ICollection <ModelElement> modelElements = shapeOrModelElements.OfType <PresentationElement>() // Filter out shapes such as labels that don't have model elements: .Where(pel => pel.ModelElement != null) .Select(pel => pel.ModelElement).ToList(); ElementGroup melGroup = base.CreateElementGroup(modelElements, closureType); group.AddRange(melGroup.GetElements()); } return(group); // 2011-03-21 Thanks to Joeul in VMSDK Forum for a bug fix here. // http://social.msdn.microsoft.com/Forums/en-US/dslvsarchx/thread/0b0b16d4-6014-4b35-9e5a-e27ea02e0ee3 }
/* 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> /// Create an EGP to add to the clipboard. /// Called when the elements to be copied or dragged have been /// collected into an ElementGroup and after the roots have been marked. /// This override ensures that the shapes and connectors of each element and relationship are included. /// </summary> /// <param name="elementGroup">Group of elements and maybe shapes</param> /// <param name="elements">The original set of elements to be added, not including children, relationships, etc. Typically, the current selection.</param> /// <param name="closureType">Copy or Delete - specifies which propagation scheme to follow</param> /// <returns>EGP </returns> protected override ElementGroupPrototype CreateElementGroupPrototype(ElementGroup elementGroup, ICollection <ModelElement> elements, ClosureType closureType) { // Get the elements already in the group: ModelElement[] mels = elementGroup.ModelElements .Concat(elementGroup.ElementLinks) // Omit if the paste target is not the diagram. .ToArray(); // Get their shapes and connectors: IEnumerable <PresentationElement> shapes = mels.SelectMany(mel => PresentationViewsSubject.GetPresentation(mel)); elementGroup.AddRange(shapes, true); return(base.CreateElementGroupPrototype(elementGroup, elements, closureType)); }