/// Ensures that DSL Diagram and Entity Diagram are in sync. /// This method also update the xref link between DSL Diagram and Model Diagram. private void ApplyLayoutInformationFromModelDiagram() { var artifact = Context.GetEFArtifactService().Artifact as EntityDesignArtifact; Debug.Assert(artifact != null, "Could not get the instance of EntityDesignArtifact from EditingContext."); if (artifact != null && artifact.IsDesignerSafe) { DesignerModel.Diagram modelDiagram = null; if (artifact.DesignerInfo != null && artifact.DesignerInfo.Diagrams != null) { modelDiagram = String.IsNullOrEmpty(_diagramId) ? artifact.DesignerInfo.Diagrams.FirstDiagram : artifact.DesignerInfo.Diagrams.GetDiagram(_diagramId); } // At this point DSL diagram should have been set. var diagram = Diagram as EntityDesignerDiagram; Debug.Assert(diagram != null, "Why does the DSL diagram is null?"); if (modelDiagram != null && diagram != null) { EntityModelToDslModelTranslatorStrategy.TranslateDiagram(diagram, modelDiagram); if (CurrentDesigner != null) { CurrentDesigner.ZoomAtViewCenter((float)modelDiagram.ZoomLevel.Value / 100); } } } }
internal static void TranslateDiagram(EntityDesignerDiagram diagram, DesignerModel.Diagram modelDiagram) { var viewModel = diagram.ModelElement; viewModel.ModelXRef.Add(modelDiagram, diagram, viewModel.EditingContext); using (var t = diagram.Store.TransactionManager.BeginTransaction("Translate diagram", true)) { // list of shapes that don't have corresponding element in model and require auto-layout var shapesToAutoLayout = new List <ViewModelDiagram.ShapeElement>(); // try to find object in model for each shape on a diagram foreach (var shapeElement in diagram.NestedChildShapes) { var entityShape = shapeElement as EntityTypeShape; if (entityShape != null && entityShape.ModelElement != null) { var modelEntity = viewModel.ModelXRef.GetExisting(entityShape.ModelElement) as ModelEntityType; if (modelEntity != null) { var modelEntityTypeShape = modelDiagram.EntityTypeShapes.FirstOrDefault(ets => ets.EntityType.Target == modelEntity); if (modelEntityTypeShape != null) { viewModel.ModelXRef.Add(modelEntityTypeShape, entityShape, viewModel.EditingContext); var rectangle = new ViewModelDiagram.RectangleD( modelEntityTypeShape.PointX.Value, modelEntityTypeShape.PointY.Value , modelEntityTypeShape.Width.Value, 0.0); entityShape.AbsoluteBounds = rectangle; entityShape.IsExpanded = modelEntityTypeShape.IsExpanded.Value; entityShape.FillColor = modelEntityTypeShape.FillColor.Value; } } if (viewModel.ModelXRef.GetExisting(entityShape) == null) { shapesToAutoLayout.Add(entityShape); } continue; } var associationConnector = shapeElement as AssociationConnector; if (associationConnector != null && associationConnector.ModelElement != null) { var modelAssociation = viewModel.ModelXRef.GetExisting(associationConnector.ModelElement) as ModelAssociation; if (modelAssociation != null) { var modelAssociationConnector = modelDiagram.AssociationConnectors.FirstOrDefault(ac => ac.Association.Target == modelAssociation); if (modelAssociationConnector != null) { viewModel.ModelXRef.Add(modelAssociationConnector, associationConnector, viewModel.EditingContext); TranslateAssociationConnectors(associationConnector, modelAssociationConnector, shapesToAutoLayout); } } continue; } var inheritanceConnector = shapeElement as InheritanceConnector; if (inheritanceConnector != null && inheritanceConnector.ModelElement != null) { var entityTypeBase = viewModel.ModelXRef.GetExisting(inheritanceConnector.ModelElement) as EntityTypeBaseType; var modelEntity = entityTypeBase.Parent as ModelEntityType; if (modelEntity != null) { var modelInheritanceConnector = modelDiagram.InheritanceConnectors.FirstOrDefault(ic => ic.EntityType.Target == modelEntity); if (modelInheritanceConnector != null) { viewModel.ModelXRef.Add(modelInheritanceConnector, inheritanceConnector, viewModel.EditingContext); TranslateInheritanceConnectors(inheritanceConnector, modelInheritanceConnector, shapesToAutoLayout); } } continue; } } diagram.AutoLayoutDiagram(shapesToAutoLayout); // initiate zoom level, grid and scalar property options diagram.ZoomLevel = modelDiagram.ZoomLevel.Value; diagram.ShowGrid = modelDiagram.ShowGrid.Value; diagram.SnapToGrid = modelDiagram.SnapToGrid.Value; diagram.DisplayNameAndType = modelDiagram.DisplayType.Value; diagram.DiagramId = modelDiagram.Id.Value; diagram.Title = modelDiagram.Name.Value; t.Commit(); } }
private static void RetrieveModelElementsFromDiagram( DesignerModel.Diagram diagram, out IList <ModelEntityType> entityTypes, out IList <ModelAssociation> associations) { entityTypes = new List <ModelEntityType>(); associations = new List <ModelAssociation>(); var elementsToDelete = new List <EFElement>(); foreach (var entityTypeShape in diagram.EntityTypeShapes) { if (entityTypeShape.EntityType != null && entityTypeShape.EntityType.Status == BindingStatus.Known) { if (entityTypes.Contains(entityTypeShape.EntityType.Target)) { elementsToDelete.Add(entityTypeShape); } else { entityTypes.Add(entityTypeShape.EntityType.Target); } } } foreach (var associationConnector in diagram.AssociationConnectors) { if (associationConnector.Association != null && associationConnector.Association.Status == BindingStatus.Known) { if (associations.Contains(associationConnector.Association.Target)) { elementsToDelete.Add(associationConnector); } else { associations.Add(associationConnector.Association.Target); } } } if (elementsToDelete.Any()) { Debug.Fail( string.Format( CultureInfo.CurrentCulture, "Found {0} duplicate items in diagram, which will be deleted as part of loading: {1}", elementsToDelete.Count, string.Join(",", elementsToDelete.Select(e => e.DisplayName)))); if (diagram.Artifact.CanEditArtifact()) { // Don't use an EfiTransaction here, since we just want to clean up the XML and avoid triggering diagram ui deletes using (var tx = diagram.Artifact.XmlModelProvider.BeginTransaction("LoadDiagram", "Remove duplicate diagram elements")) { foreach (var element in elementsToDelete) { element.Delete(); } tx.Commit(); } } else { Debug.Fail( string.Format( CultureInfo.CurrentCulture, "Could not delete duplicate diagram items, proceeding with load and ignoring duplicates")); } } }
private static EntityDesignerDiagram TranslateDiagramValues(EntityDesignerViewModel viewModel, DesignerModel.Diagram modelDiagram) { var diagram = viewModel.GetDiagram(); Debug.Assert(diagram != null, "Why diagram is null?"); if (diagram != null) { if (viewModel.ModelXRef.ContainsKey(modelDiagram) == false) { viewModel.ModelXRef.Add(modelDiagram, diagram, viewModel.EditingContext); } using (var t = diagram.Store.TransactionManager.BeginTransaction("Translate diagram values", true)) { // set zoom level, grid and scalar property options diagram.ZoomLevel = modelDiagram.ZoomLevel.Value; diagram.ShowGrid = modelDiagram.ShowGrid.Value; diagram.SnapToGrid = modelDiagram.SnapToGrid.Value; diagram.DisplayNameAndType = modelDiagram.DisplayType.Value; diagram.Title = modelDiagram.Name.Value; diagram.DiagramId = modelDiagram.Id.Value; t.Commit(); } } return(diagram); }
internal override DslModeling.ModelElement TranslateModelToDslModel(EFObject modelElement, DslModeling.Partition partition) { DesignerModel.Diagram diagram = null; if (modelElement != null) { diagram = modelElement as DesignerModel.Diagram; if (diagram == null) { throw new ArgumentException("modelElement should be a diagram"); } } // get the service so that we can access the root of the entity model var service = _editingContext.GetEFArtifactService(); if (service == null) { throw new InvalidOperationException(EntityDesignerResources.Error_NoArtifactService); } EntityDesignerViewModel entityViewModel = null; var entityDesignArtifact = service.Artifact as EntityDesignArtifact; Debug.Assert(entityDesignArtifact != null, "Artifact is not type of EntityDesignArtifact"); if (entityDesignArtifact != null) { // Only translate the Escher Model to Dsl Model if the artifact is designer safe. if (entityDesignArtifact.IsDesignerSafe) { // now get the root of the model. var model = entityDesignArtifact.ConceptualModel; Debug.Assert(model != null, "Could not get ConceptualModel from the artifact."); if (model != null) { entityViewModel = ModelToDesignerModelXRef.GetNewOrExisting(_editingContext, model, partition) as EntityDesignerViewModel; entityViewModel.Namespace = model.Namespace.Value; // If the passed-in diagram is null, retrieve the first diagram if available. if (diagram == null && entityDesignArtifact.DesignerInfo() != null && entityDesignArtifact.DesignerInfo().Diagrams != null && entityDesignArtifact.DesignerInfo().Diagrams.FirstDiagram != null) { diagram = entityDesignArtifact.DesignerInfo().Diagrams.FirstDiagram; } IList <ModelEntityType> entities; IList <ModelAssociation> associations; if (diagram != null) { RetrieveModelElementsFromDiagram(diagram, out entities, out associations); } else { entities = model.EntityTypes().ToList(); associations = model.Associations().ToList(); } TranslateEntityModel(entities, associations, entityViewModel); } } else { // return empty view model if the artifact is not designer safe so the Diagram can show safe-mode watermark entityViewModel = new EntityDesignerViewModel(partition); entityViewModel.EditingContext = _editingContext; } } return(entityViewModel); }
/// <summary> /// This method loads the DSL view model with the items in the artifact's C-Model. /// </summary> internal void ReloadModel(EntityDesignerViewModel viewModel) { var diagram = viewModel.GetDiagram(); if (diagram == null) { // empty DSL diagram return; } // get our artifact var artifact = EditingContextManager.GetArtifact(viewModel.EditingContext) as EntityDesignArtifact; Debug.Assert(artifact != null); var serializationResult = new SerializationResult(); var serializationContext = new SerializationContext(GetDirectory(viewModel.Store), artifact.Uri.LocalPath, serializationResult); var transactionContext = new TransactionContext(); transactionContext.Add(SerializationContext.TransactionContextKey, serializationContext); var workaroundFixSerializationTransactionValue = false; if (viewModel.Store.PropertyBag.ContainsKey("WorkaroundFixSerializationTransaction")) { workaroundFixSerializationTransactionValue = (bool)viewModel.Store.PropertyBag["WorkaroundFixSerializationTransaction"]; } try { // To fix performance issue during reload, we turn-off layout during "serialization". viewModel.Store.PropertyBag["WorkaroundFixSerializationTransaction"] = true; using (var t = viewModel.Store.TransactionManager.BeginTransaction("ReloadModel", true, transactionContext)) { if (artifact.ConceptualModel() == null) { return; } DesignerModel.Diagram diagramModel = null; // If DiagramId is not string empty, try to get the diagram from the artifact. // There is a situation where we could not find the diagram given an ID (for example: EDMX Model's Diagram that is created by VS before SQL 11; // In that case, we assign temporary ID to the diagram and a new ID will be generated every time the model is reloaded.) // We could safely choose the first diagram since multiple diagrams feature didn't exist in VS prior to SQL11 release. if (!string.IsNullOrEmpty(diagram.DiagramId)) { diagramModel = artifact.DesignerInfo.Diagrams.GetDiagram(diagram.DiagramId); } if (diagramModel == null) { diagramModel = artifact.DesignerInfo.Diagrams.FirstDiagram; } if (diagramModel != null) { // Re-establish the xref between Escher conceptual model and DSL root model. // and between Escher Diagram model and DSL diagram model. Debug.Assert(viewModel.ModelXRef != null, "Why ModelXRef is null?"); if (viewModel.ModelXRef != null) { viewModel.ModelXRef.Add(artifact.ConceptualModel(), viewModel, viewModel.EditingContext); viewModel.ModelXRef.Add(diagramModel, diagram, viewModel.EditingContext); ModelTranslatorContextItem.GetEntityModelTranslator(viewModel.EditingContext) .TranslateModelToDslModel(diagramModel, viewModel.Partition); } } if (t.IsActive) { t.Commit(); } } } finally { viewModel.Store.PropertyBag["WorkaroundFixSerializationTransaction"] = workaroundFixSerializationTransactionValue; } }
private static void InjectInheritanceConnectorCommand( CommandProcessorContext commandProcessorContext, HashSet <ShapeChangeInformation> shapeChangeInfoSet, Diagram diagram, EntityTypeBaseType baseType, XObjectChange changeAction) { // First check to see if there is already a change in the original transaction // for the InheritanceConnector that matches the one that we're getting var shapeChangeInfoToQuery = new ShapeChangeInformation { ChangeType = changeAction, ModelEFObject = baseType.OwnerEntityType, DiagramId = diagram.Id.Value }; var shapeChangeInfoExists = shapeChangeInfoSet.Contains(shapeChangeInfoToQuery); if (changeAction == XObjectChange.Add && shapeChangeInfoExists == false) { var participatingEntityTypes = new List <EntityType>(); var derivedEntityType = baseType.Parent as EntityType; Debug.Assert(derivedEntityType != null, "Where is the parent EntityType of this BaseType attribute?"); if (derivedEntityType != null) { // The inheritance connector is added if // - the participating entities exists in the diagram. // or // - the participating entities will be added in the current transaction. participatingEntityTypes.Add(derivedEntityType); participatingEntityTypes.Add(((ConceptualEntityType)derivedEntityType).BaseType.Target); foreach (var entityType in participatingEntityTypes) { if (diagram.EntityTypeShapes.Where(ets => ets.EntityType.Target == entityType).Any() || shapeChangeInfoSet.Where( sc => sc.DiagramId == diagram.Id.Value && sc.ModelEFObject == entityType && sc.ChangeType == XObjectChange.Add) .Any()) { continue; } // If it reach this point, that means that we should not add inheritance connector in the diagram. return; } var cmd = new CreateInheritanceConnectorCommand(diagram, derivedEntityType); CommandProcessor.InvokeSingleCommand(commandProcessorContext, cmd); } } else if (changeAction == XObjectChange.Remove && shapeChangeInfoExists == false) { // this is happening before the transaction is taking place so we are free to look up anti-dependencies // on this delete var owningEntityType = baseType.Parent as EntityType; if (owningEntityType != null) { foreach ( var inheritanceConnector in owningEntityType.GetAntiDependenciesOfType <InheritanceConnector>() .Where(ic => ic.Diagram != null && ic.Diagram.Id == diagram.Id.Value)) { if (inheritanceConnector != null) { var deleteInheritanceConnectorCommand = inheritanceConnector.GetDeleteCommand(); CommandProcessor.InvokeSingleCommand(commandProcessorContext, deleteInheritanceConnectorCommand); } } } } }
private static void InjectAssociationConnectorCommand( CommandProcessorContext commandProcessorContext, HashSet <ShapeChangeInformation> shapeChangeInfoSet, Diagram diagram, Association association, XObjectChange changeAction) { // First check to see if there is already a change in the original transaction // for the AssociationConnector that matches the one that we're getting var shapeChangeInfoToQuery = new ShapeChangeInformation { ChangeType = changeAction, ModelEFObject = association, DiagramId = diagram.Id.Value }; var shapeChangeInfoExists = shapeChangeInfoSet.Contains(shapeChangeInfoToQuery); // We only want to create model diagram if the transaction is originated from this diagram. if (changeAction == XObjectChange.Add && shapeChangeInfoExists == false) { // The association connector is added if // - the participating entities are in the diagram. // or // - the participating entities will be added in the current transaction. foreach (var end in association.AssociationEnds()) { if (end.Type != null && end.Type.Target != null) { if (diagram.EntityTypeShapes.Where(ets => ets.EntityType.Target == end.Type.Target).Any() || shapeChangeInfoSet.Where( sc => sc.DiagramId == diagram.Id.Value && sc.ModelEFObject == end.Type.Target && sc.ChangeType == XObjectChange.Add).Any()) { continue; } } // If it reach this point, that means that we should not add association connector in the diagram. return; } var cmd = new CreateAssociationConnectorCommand(diagram, association); CommandProcessor.InvokeSingleCommand(commandProcessorContext, cmd); } else if (changeAction == XObjectChange.Remove && shapeChangeInfoExists == false) { // this is happening before the transaction is taking place so we are free to look up anti-dependencies on this delete foreach ( var associationConnector in association.GetAntiDependenciesOfType <AssociationConnector>() .Where(ac => ac.Diagram != null && ac.Diagram.Id == diagram.Id.Value)) { if (associationConnector != null) { var deleteAssociationConnectorCommand = associationConnector.GetDeleteCommand(); CommandProcessor.InvokeSingleCommand(commandProcessorContext, deleteAssociationConnectorCommand); } } } }
internal void AddDiagram(Diagram diagram) { _diagrams.Add(diagram); }
private static void InjectEntityTypeShapeCommand( CommandProcessorContext commandProcessorContext, HashSet <ShapeChangeInformation> shapeChangeInfoSet, Diagram diagram, ConceptualEntityType entityType, XObjectChange changeAction) { // First check to see if there is already a change in the original transaction // for the EntityTypeShape that matches the one that we're getting var shapeChangeInfoToQuery = new ShapeChangeInformation { ChangeType = changeAction, ModelEFObject = entityType, DiagramId = diagram.Id.Value }; var shapeChangeInfoExists = shapeChangeInfoSet.Contains(shapeChangeInfoToQuery); // We only want to create model diagram if the transaction is originated from this diagram. if (changeAction == XObjectChange.Add) { // We only want to inject the entity-type-shape if the transaction is originated from the passed in diagram. if (commandProcessorContext != null && commandProcessorContext.EfiTransaction != null) { var contextItem = commandProcessorContext.EfiTransaction.GetContextValue <DiagramContextItem>( EfiTransactionOriginator.TransactionOriginatorDiagramId); if (contextItem != null && contextItem.DiagramId == diagram.Id.Value) { // look in the dictionary for an 'add' to an EntityTypeShape that points to this modelobject. if (shapeChangeInfoExists == false) { var cmd = new CreateEntityTypeShapeCommand(diagram, entityType); CommandProcessor.InvokeSingleCommand(commandProcessorContext, cmd); } // We have the ability to create an EntityType and an Inheritance in one transaction, so we need // to check for it here. if (entityType.BaseType.Target != null) { InjectInheritanceConnectorCommand( commandProcessorContext, shapeChangeInfoSet, diagram, entityType.BaseType, changeAction); } } } } else if (changeAction == XObjectChange.Remove && shapeChangeInfoExists == false) { // this is happening before the transaction is taking place so we are free to look up anti-dependencies // on this delete foreach ( var entityTypeShape in entityType.GetAntiDependenciesOfType <EntityTypeShape>() .Where(ets => ets.Diagram != null && ets.Diagram.Id == diagram.Id.Value)) { if (entityTypeShape != null) { var deleteEntityTypeShapeCommand = entityTypeShape.GetDeleteCommand(); CommandProcessor.InvokeSingleCommand(commandProcessorContext, deleteEntityTypeShapeCommand); } } } }